From 4908754cebf03275770a56f53241b240bdb9ac7a Mon Sep 17 00:00:00 2001 From: Rajat Talesra Date: Fri, 13 Sep 2019 14:03:21 +0530 Subject: [PATCH 01/24] Exploration Player base code for activity and fragment --- app/src/main/AndroidManifest.xml | 1 + .../oppia/app/activity/ActivityComponent.kt | 2 ++ .../oppia/app/fragment/FragmentComponent.kt | 4 ++++ .../player/exploration/ExplorationActivity.kt | 16 +++++++++++++ .../ExplorationActivityController.kt | 18 ++++++++++++++ .../player/exploration/ExplorationFragment.kt | 23 ++++++++++++++++++ .../ExplorationFragmentController.kt | 20 ++++++++++++++++ .../oppia/app/player/state/StateFragment.kt | 24 +++++++++++++++++++ .../player/state/StateFragmentController.kt | 22 +++++++++++++++++ .../main/res/layout/exploration_activity.xml | 8 +++++++ .../main/res/layout/exploration_fragment.xml | 12 ++++++++++ app/src/main/res/layout/state_fragment.xml | 12 ++++++++++ 12 files changed, 162 insertions(+) create mode 100755 app/src/main/java/org/oppia/app/player/exploration/ExplorationActivity.kt create mode 100755 app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt create mode 100755 app/src/main/java/org/oppia/app/player/exploration/ExplorationFragment.kt create mode 100755 app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt create mode 100755 app/src/main/java/org/oppia/app/player/state/StateFragment.kt create mode 100755 app/src/main/java/org/oppia/app/player/state/StateFragmentController.kt create mode 100755 app/src/main/res/layout/exploration_activity.xml create mode 100755 app/src/main/res/layout/exploration_fragment.xml create mode 100755 app/src/main/res/layout/state_fragment.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a25c9ab2754..c632728593b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/OppiaTheme"> + diff --git a/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt b/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt index 067c44381bb..7102ac5af84 100644 --- a/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt +++ b/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt @@ -5,6 +5,7 @@ import dagger.BindsInstance import dagger.Subcomponent import org.oppia.app.fragment.FragmentComponent import org.oppia.app.home.HomeActivity +import org.oppia.app.player.exploration.ExplorationActivity import javax.inject.Provider /** Root subcomponent for all activities. */ @@ -19,5 +20,6 @@ interface ActivityComponent { fun getFragmentComponentBuilderProvider(): Provider + fun inject(explorationActivity: ExplorationActivity) fun inject(homeActivity: HomeActivity) } diff --git a/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt b/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt index d56fdf0c26c..1f3efd3af22 100644 --- a/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt +++ b/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt @@ -4,6 +4,8 @@ import androidx.fragment.app.Fragment import dagger.BindsInstance import dagger.Subcomponent import org.oppia.app.home.HomeFragment +import org.oppia.app.player.exploration.ExplorationFragment +import org.oppia.app.player.state.StateFragment /** Root subcomponent for all fragments. */ @Subcomponent @@ -15,5 +17,7 @@ interface FragmentComponent { fun build(): FragmentComponent } + fun inject(explorationFragment: ExplorationFragment) fun inject(homeFragment: HomeFragment) + fun inject(stateFragment: StateFragment) } diff --git a/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivity.kt b/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivity.kt new file mode 100755 index 00000000000..5fef4903235 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivity.kt @@ -0,0 +1,16 @@ +package org.oppia.app.player.exploration + +import android.os.Bundle +import org.oppia.app.activity.InjectableAppCompatActivity +import javax.inject.Inject + +/** The starting point for exploration*/ +class ExplorationActivity : InjectableAppCompatActivity() { + @Inject lateinit var explorationActivityController: ExplorationActivityController + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + activityComponent.inject(this) + explorationActivityController.handleOnCreate() + } +} diff --git a/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt b/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt new file mode 100755 index 00000000000..1d8ad338bf6 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt @@ -0,0 +1,18 @@ +package org.oppia.app.player.exploration + +import androidx.appcompat.app.AppCompatActivity +import org.oppia.app.R +import org.oppia.app.activity.ActivityScope +import javax.inject.Inject + +/** The controller for [ExplorationActivity]. */ +@ActivityScope +class ExplorationActivityController @Inject constructor(private val activity: AppCompatActivity) { + fun handleOnCreate() { + activity.setContentView(R.layout.exploration_activity) + activity.supportFragmentManager.beginTransaction().add( + R.id.exploration_fragment_placeholder, + ExplorationFragment() + ).commitNow() + } +} diff --git a/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragment.kt b/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragment.kt new file mode 100755 index 00000000000..9e7845cde82 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragment.kt @@ -0,0 +1,23 @@ +package org.oppia.app.player.exploration + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import org.oppia.app.fragment.InjectableFragment +import javax.inject.Inject + +/** Fragment that contains displays single exploration.*/ +class ExplorationFragment : InjectableFragment() { + @Inject lateinit var explorationFragmentController: ExplorationFragmentController + + override fun onAttach(context: Context?) { + super.onAttach(context) + fragmentComponent.inject(this) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return explorationFragmentController.handleCreateView(inflater, container) + } +} diff --git a/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt b/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt new file mode 100755 index 00000000000..2d3a6386703 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt @@ -0,0 +1,20 @@ +package org.oppia.app.player.exploration + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import org.oppia.app.databinding.ExplorationFragmentBinding +import org.oppia.app.fragment.FragmentScope +import javax.inject.Inject + +/** The controller for [ExplorationFragment]. */ +@FragmentScope +class ExplorationFragmentController @Inject constructor( + private val fragment: Fragment +) { + fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { + val binding = ExplorationFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) + return binding.root + } +} diff --git a/app/src/main/java/org/oppia/app/player/state/StateFragment.kt b/app/src/main/java/org/oppia/app/player/state/StateFragment.kt new file mode 100755 index 00000000000..d5d7836d5c5 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/state/StateFragment.kt @@ -0,0 +1,24 @@ +package org.oppia.app.player.state + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import org.oppia.app.fragment.InjectableFragment +import javax.inject.Inject + +/** Fragment that contains displays current state of exploration.*/ +class StateFragment : InjectableFragment() { + @Inject + lateinit var stateFragmentController: StateFragmentController + + override fun onAttach(context: Context?) { + super.onAttach(context) + fragmentComponent.inject(this) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return stateFragmentController.handleCreateView(inflater, container) + } +} diff --git a/app/src/main/java/org/oppia/app/player/state/StateFragmentController.kt b/app/src/main/java/org/oppia/app/player/state/StateFragmentController.kt new file mode 100755 index 00000000000..e3f53a17f43 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/state/StateFragmentController.kt @@ -0,0 +1,22 @@ +package org.oppia.app.player.state + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import org.oppia.app.databinding.ExplorationFragmentBinding +import org.oppia.app.databinding.HomeFragmentBinding +import org.oppia.app.databinding.StateFragmentBinding +import org.oppia.app.fragment.FragmentScope +import javax.inject.Inject + +/** The controller for [StateFragment]. */ +@FragmentScope +class StateFragmentController @Inject constructor( + private val fragment: Fragment +) { + fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { + val binding = StateFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) + return binding.root + } +} diff --git a/app/src/main/res/layout/exploration_activity.xml b/app/src/main/res/layout/exploration_activity.xml new file mode 100755 index 00000000000..a4b2eeb46ef --- /dev/null +++ b/app/src/main/res/layout/exploration_activity.xml @@ -0,0 +1,8 @@ + + diff --git a/app/src/main/res/layout/exploration_fragment.xml b/app/src/main/res/layout/exploration_fragment.xml new file mode 100755 index 00000000000..2df94f72dd5 --- /dev/null +++ b/app/src/main/res/layout/exploration_fragment.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/state_fragment.xml b/app/src/main/res/layout/state_fragment.xml new file mode 100755 index 00000000000..2df94f72dd5 --- /dev/null +++ b/app/src/main/res/layout/state_fragment.xml @@ -0,0 +1,12 @@ + + + + + + + + + From 8e453904ea8f35cc0c379ea44cd3b5ff6275eb16 Mon Sep 17 00:00:00 2001 From: Rajat Talesra Date: Fri, 13 Sep 2019 14:42:16 +0530 Subject: [PATCH 02/24] Fake Data Provider --- .../java/org/oppia/app/FakeDataProvider.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 app/src/main/java/org/oppia/app/FakeDataProvider.kt diff --git a/app/src/main/java/org/oppia/app/FakeDataProvider.kt b/app/src/main/java/org/oppia/app/FakeDataProvider.kt new file mode 100755 index 00000000000..a76b98d689e --- /dev/null +++ b/app/src/main/java/org/oppia/app/FakeDataProvider.kt @@ -0,0 +1,27 @@ +package org.oppia.app + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import org.oppia.data.backends.gae.model.GaeExplorationContainer + +// Remove this file at later stage once domain and model module are working. +class FakeDataProvider() { + companion object { + const val TOPIC_SERVICE_RESPONSE: String = + "{\"canonical_story_dicts\":[{\"title\":\"Story 1\",\"description\":\"Story Description\",\"id\":\"4wv9hSZ4F67I\"}],\"is_moderator\":true,\"is_admin\":true,\"topic_name\":\"Topic1\",\"username\":\"rt4914\",\"skill_descriptions\":{\"A9j9taXAqqkV\":\"Skill 1\"},\"user_email\":\"test@example.com\",\"iframed\":false,\"additional_story_dicts\":[],\"additional_angular_modules\":[],\"is_topic_manager\":false,\"uncategorized_skill_ids\":[],\"topic_id\":\"baWJOUFeUAnn\",\"degrees_of_mastery\":{\"A9j9taXAqqkV\":null},\"subtopics\":[{\"skill_ids\":[\"A9j9taXAqqkV\"],\"title\":\"Subtopic 1\",\"id\":1}],\"is_super_admin\":true}" + const val CLASSROOM_SERVICE_RESPONSE: String = + "{\"is_super_admin\":true,\"topic_summary_dicts\":[{\"version\":3,\"language_code\":\"en\",\"subtopic_count\":0,\"canonical_story_count\":1,\"uncategorized_skill_count\":0,\"topic_model_last_updated\":1567587844908.068,\"id\":\"BpslppK1Tb89\",\"additional_story_count\":0,\"total_skill_count\":0,\"topic_model_created_on\":1567587801448.179,\"name\":\"Math\"}],\"user_email\":\"test@example.com\",\"iframed\":false,\"username\":\"veena\",\"is_topic_manager\":false,\"is_moderator\":true,\"is_admin\":true}" + const val EXPLORATION_SERVICE_RESPONSE: String = + "{\"exploration\":{\"param_changes\":[],\"title\":\"What is a Fraction? Part 1\",\"states\":{\"Q6 on N and D\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_1\",\"html\":\"

That's great! You've really learned this well!<\\/p>\"},\"dest\":\"Final Card\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"7\\/9\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_2\",\"html\":\"

Oops, read the question carefully and try again!<\\/p>\"},\"dest\":\"Q6 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"2\\/9\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_3\",\"html\":\"

Nope, you've got the numerator and denominator in the wrong places!<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"9\\/7\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_4\",\"html\":\"

Nope! Let's have a look again at how a fraction is defined.<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"2\\/7\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"7\\/2\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_5\",\"html\":\"

You've got the right denominator! The numerator doesn't seem correct, though -- remember that the numerator of a fraction is the number of selected<\\/em> parts. Have another go?<\\/p>\"},\"dest\":\"Q6 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Contains\",\"inputs\":{\"x\":\"\\/9\"}}],\"tagged_misconception_id\":null}],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"

Nope, try again. I know you can get this!<\\/p>\"},\"dest\":\"Q6 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"rows\":{\"value\":1},\"placeholder\":{\"value\":\"Write your fraction as x\\/y.\"}},\"confirmed_unclassified_answers\":[],\"id\":\"TextInput\",\"hints\":[{\"hint_content\":{\"content_id\":\"hint_1\",\"html\":\"

Start with the denominator first. How many pieces is the whole cake cut into? That number goes on the bottom of the fraction.<\\/p>\"}},{\"hint_content\":{\"content_id\":\"hint_2\",\"html\":\"

After cutting the cake into equal parts and finding the denominator, you can find the numerator by counting how many of these parts we want.<\\/p>\"}},{\"hint_content\":{\"content_id\":\"hint_3\",\"html\":\"

Remember to write your answer in the form: numerator \\/ denominator. For example, you might write something like 3\\/5 or 1\\/6. (These are just examples -- make sure to get the numbers right!)<\\/p>\"}}]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":463869,\"needs_update\":false,\"filename\":\"content-es-98dcbbe6mf.mp3\"},\"hi-en\":{\"file_size_bytes\":310330,\"needs_update\":false,\"filename\":\"content-hi-en-b60gqlidf95aerxa2e8x9r7ldi.mp3\"}},\"feedback_4\":{},\"feedback_5\":{},\"feedback_2\":{},\"feedback_3\":{},\"feedback_1\":{},\"hint_1\":{},\"hint_2\":{},\"hint_3\":{},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

\\\"Let's try one last question,\\\" said Mr. Baker. \\\"Here's a pineapple cake cut into pieces.\\\"<\\/p><\\/oppia-noninteractive-image>

\\u00a0<\\/p>

Question 6<\\/strong>: What fraction of the cake has big red cherries in the pineapple slices?<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"feedback_4\":{},\"feedback_5\":{},\"feedback_2\":{},\"feedback_3\":{},\"feedback_1\":{},\"hint_1\":{},\"hint_2\":{},\"hint_3\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Introduction\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"\"},\"dest\":\"Problem\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"buttonText\":{\"value\":\"Continue\"}},\"confirmed_unclassified_answers\":[],\"id\":\"Continue\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":1400616,\"needs_update\":false,\"filename\":\"content-es-4lbxy0bwo4g.mp3\"},\"hi-en\":{\"file_size_bytes\":901734,\"needs_update\":false,\"filename\":\"content-hi-en-u0rzwuys9s7ur1kg3b5zsemi.mp3\"}},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

Meet Matthew!<\\/p><\\/oppia-noninteractive-image>

Matthew is a typical young man: he likes friends, sports, and eating cake! He also likes learning new things. We\\u2019ll follow Matthew as he learns about fractions and how to use them.<\\/p>

You should know the following before continuing:<\\/p>

  • The counting numbers (1, 2, 3, 4, 5, ...)<\\/li>
  • How to add, subtract, multiply, and divide these numbers<\\/li>
  • How to tell whether a number is bigger than another.<\\/li><\\/ul>

    You should also get some\\u00a0paper and a pen or pencil\\u00a0to write with, and find a quiet place to work. Be sure to take your time and go through the story at your own pace. Understanding is more important than speed!
    <\\/p>

    Ready? Click\\u00a0Continue<\\/strong>\\u00a0to get started!<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Q5 on N and D\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_1\",\"html\":\"

    Fantastic! That's exactly right! Let's try just one more.<\\/p>\"},\"dest\":\"Q6 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"3\\/5\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_2\",\"html\":\"

    Oops, that's not quite right. Did you read the question carefully? It's asking about the white <\\/em>pieces.<\\/p>\"},\"dest\":\"Q5 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"2\\/5\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_3\",\"html\":\"

    Oops, it looks like you've mixed up the numerator and denominator! Remember, the denominator is the number of pieces the whole<\\/em> cake is divided into, and it goes at the bottom <\\/em>of the fraction.
    <\\/em><\\/p>

    \\u00a0<\\/p>

    Practice makes perfect -- so, let's try practicing this again, and see if you can get it right the next time!
    <\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"5\\/2\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"5\\/3\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_4\",\"html\":\"

    Oops! Remember, here's how you write a fraction:<\\/p>

    \\u00a0<\\/p>

    \\u00a0 \\u00a0 \\u00a0 \\u00a0 \\u00a0 \\u00a0 <\\/oppia-noninteractive-math><\\/p>

    \\u00a0<\\/p>

    The number of unselected pieces shouldn't appear anywhere. Let's take a look at that again!
    <\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"2\\/3\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"3\\/2\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_5\",\"html\":\"

    Oops, make sure to read the question carefully! The answer should be a fraction, not a number. You can type a fraction using the \\\"\\/\\\" -- for example, \\\"1\\/4\\\".
    <\\/p>\"},\"dest\":\"Q5 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"3\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"2\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"5\"}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_6\",\"html\":\"

    Oops, make sure to read the question carefully! It's great that you spelled that word correctly, but the question is asking for a fraction<\\/em> as the answer :)
    <\\/p>\"},\"dest\":\"Q5 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"Denominator\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"Numerator\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"denominator\"}},{\"rule_type\":\"Equals\",\"inputs\":{\"x\":\"numerator\"}}],\"tagged_misconception_id\":null}],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"

    No, that's not it. You can get this!<\\/p>\"},\"dest\":\"Q5 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"rows\":{\"value\":1},\"placeholder\":{\"value\":\"Write your fraction as x\\/y.\"}},\"confirmed_unclassified_answers\":[],\"id\":\"TextInput\",\"hints\":[{\"hint_content\":{\"content_id\":\"hint_1\",\"html\":\"

    You'll need to enter your answer as a number, then \\\"\\/\\\", then another number.<\\/p>

    \\u00a0<\\/p>

    For example, if the numerator is 1 and the denominator is 4, the fraction to type is 1\\/4.
    <\\/p>\"}},{\"hint_content\":{\"content_id\":\"hint_2\",\"html\":\"

    Remember, the denominator of a fraction is the number of parts that the whole<\\/em> thing is cut into. If you're typing, it's the number on\\u00a0the right of the \\\"\\/\\\". For example, the denominator in 2\\/8 is 8.<\\/p>\"}}]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":366067,\"needs_update\":false,\"filename\":\"content-es-5ope2fob1d.mp3\"},\"hi-en\":{\"file_size_bytes\":267166,\"needs_update\":false,\"filename\":\"content-hi-en-ypcygr4e6bq34ahzmx2h85mi.mp3\"}},\"feedback_4\":{},\"feedback_2\":{},\"feedback_3\":{},\"feedback_1\":{},\"feedback_6\":{},\"hint_1\":{},\"hint_2\":{},\"feedback_5\":{},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

    Mr. Baker showed Matthew his napkin drawing again, then asked him a question.<\\/p><\\/oppia-noninteractive-image>

    \\u00a0<\\/p>

    Question 5<\\/strong>: What fraction of the circle is shown by the white<\\/em> pieces?
    <\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"feedback_4\":{},\"feedback_2\":{},\"feedback_3\":{},\"feedback_1\":{},\"feedback_6\":{},\"hint_1\":{},\"hint_2\":{},\"feedback_5\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Into the Bakery\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"\"},\"dest\":\"Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"buttonText\":{\"value\":\"Continue\"}},\"confirmed_unclassified_answers\":[],\"id\":\"Continue\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":1275612,\"needs_update\":false,\"filename\":\"content-es-tgwpja7skis.mp3\"},\"hi-en\":{\"file_size_bytes\":758640,\"needs_update\":false,\"filename\":\"content-hi-en-u5hw257jm4723cn9nh7x2yb9.mp3\"}},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

    As Matthew entered the bakery, a kind-looking man looked up from the counter and smiled at him.<\\/p><\\/oppia-noninteractive-image>

    \\u00a0<\\/p>

    \\\"Hi there!\\\" he said. \\\"My name\\u2019s Mr. Baker. What would you like today?\\\"<\\/p>

    \\\"The chocolate cake in the window!\\\" Matthew answered.<\\/p>

    \\u201cDo you want all of it?\\\" asked Mr. Baker.<\\/p>

    \\\"Ummmm.... no,\\\" said Matthew. He knew how to ask for one or two or three cakes. But he didn\\u2019t want the whole cake. He just wanted part of it.<\\/p>

    \\u201cYou know, you don\\u2019t need to buy the whole thing,\\u201d Mr. Baker said kindly. \\u201cI can cut a small piece for\\u00a0you,\\u00a0if you like. Just tell me how much. What fraction<\\/strong> of the cake would you like?\\u201d<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Q2 on N and D\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_1\",\"html\":\"

    Great! Let's try another one.<\\/p>\"},\"dest\":\"Q3 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":0}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_2\",\"html\":\"

    That's OK, let's look at it again.<\\/p>\"},\"dest\":\"Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":2}}],\"tagged_misconception_id\":null}],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"

    Nope, let's look at that again. When talking about numerators and denominators, it doesn't matter which number is bigger or smaller. We only care about whether it's at the top or at the bottom.<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"choices\":{\"value\":[\"

    The numerator.<\\/p>\",\"

    The denominator.<\\/p>\",\"

    I can't remember!<\\/p>\"]}},\"confirmed_unclassified_answers\":[],\"id\":\"MultipleChoiceInput\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"hi-en\":{\"file_size_bytes\":453563,\"needs_update\":false,\"filename\":\"content-hi-en-7ti730h0sphao2ezo6jxb9be29.mp3\"},\"es\":{\"file_size_bytes\":676027,\"needs_update\":false,\"filename\":\"content-es-e2k3gys7iuk.mp3\"}},\"feedback_2\":{},\"feedback_1\":{},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

    \\\"Very good!\\\" said Mr. Baker. \\\"By the way, we can also write the fraction as '4\\/7', which means the same thing as\\u00a0<\\/oppia-noninteractive-math>. If you're at a computer, it's easier to type fractions that way. Let's try another question.\\\"
    <\\/p>

    Mr. Baker wrote <\\/oppia-noninteractive-math>\\u00a0on a napkin.
    <\\/p>

    Question 2:<\\/strong>\\u00a0What is the \\\"9\\\" in the fraction <\\/oppia-noninteractive-math>?
    <\\/p>

    <\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"feedback_2\":{},\"feedback_1\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Final Card\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":null,\"customization_args\":{\"recommendedExplorationIds\":{\"value\":[]}},\"confirmed_unclassified_answers\":[],\"id\":\"EndExploration\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":729119,\"needs_update\":false,\"filename\":\"content-es-t9cl5jt483p.mp3\"},\"hi-en\":{\"file_size_bytes\":402767,\"needs_update\":false,\"filename\":\"content-hi-en-frhf4uhp5zxb2ejlgcs68ncdi.mp3\"}}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

    \\\"Congratulations, Matthew!\\\" said Mr. Baker. \\\"Here are some cookies for you. You've earned them!\\\"<\\/p><\\/oppia-noninteractive-image>

    Mr. Baker smiled as Matthew happily ate his cookies. \\\"When you're done with those, I have some very interesting things to tell you about fractions. And then ... let's see about getting you some of that chocolate cake to take home!\\\"<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{}}},\"solicit_answer_details\":false},\"Q4 on N and D\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_1\",\"html\":\"

    Exactly! Let's try another one.<\\/p>\"},\"dest\":\"Q5 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"IsInRegion\",\"inputs\":{\"x\":\"Region1\"}}],\"tagged_misconception_id\":null}],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"

    Nope, let's look at that again.<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"highlightRegionsOnHover\":{\"value\":true},\"imageAndRegions\":{\"value\":{\"labeledRegions\":[{\"region\":{\"regionType\":\"Rectangle\",\"area\":[[0.766725352112676,0.017262404703450057],[0.983274647887324,0.9815342744540638]]},\"label\":\"Region1\"},{\"region\":{\"regionType\":\"Rectangle\",\"area\":[[0.016725352112676055,0.012416817418271095],[0.238556338028169,0.966997512598527]]},\"label\":\"Region2\"},{\"region\":{\"regionType\":\"Rectangle\",\"area\":[[0.26672535211267606,0.012416817418271095],[0.49911971830985913,0.9960710363096007]]},\"label\":\"Region3\"},{\"region\":{\"regionType\":\"Rectangle\",\"area\":[[0.5184859154929577,0.002725642847913167],[0.7350352112676056,0.9912254490244218]]},\"label\":\"Region4\"}],\"imagePath\":\"ND4_height_218_width_600.png\"}}},\"confirmed_unclassified_answers\":[],\"id\":\"ImageClickInput\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":253276,\"needs_update\":false,\"filename\":\"content-es-gv0s5h0j2li.mp3\"},\"hi-en\":{\"file_size_bytes\":143005,\"needs_update\":false,\"filename\":\"content-hi-en-1ufx00uksjlgfytae9n2sxlxr.mp3\"}},\"default_outcome\":{},\"feedback_1\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

    Question 4<\\/strong>:\\u00a0Select the fraction in the picture with a denominator of 4, and a numerator of 3.<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{},\"feedback_1\":{}}},\"solicit_answer_details\":false},\"Q3 on N and D\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_1\",\"html\":\"

    Very good! Let's try another one!<\\/p>\"},\"dest\":\"Q4 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":[\"

    <\\/oppia-noninteractive-math>
    <\\/p>\",\"

    2\\/3<\\/p>\"]}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_2\",\"html\":\"

    No, 3\\/7 is not correct -- the 3 is in the numerator. Let's take a look at that again.<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"ContainsAtLeastOneOf\",\"inputs\":{\"x\":[\"

    3\\/7<\\/p>\"]}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_3\",\"html\":\"

    No, <\\/oppia-noninteractive-math>\\u00a0is not correct -- the 3 is in the numerator. Let's take a look at that again.<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"ContainsAtLeastOneOf\",\"inputs\":{\"x\":[\"

    <\\/oppia-noninteractive-math>
    <\\/p>\"]}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_4\",\"html\":\"

    That's good, but there are more! Can you find other fractions with a denominator of \\\"3\\\"? You can select more than one choice.<\\/p>\"},\"dest\":\"Q3 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"DoesNotContainAtLeastOneOf\",\"inputs\":{\"x\":[\"

    <\\/oppia-noninteractive-math>
    <\\/p>\",\"

    2\\/3<\\/p>\"]}}],\"tagged_misconception_id\":null}],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"

    Hmm, let's try that again.<\\/p>\"},\"dest\":\"Q3 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"maxAllowableSelectionCount\":{\"value\":4},\"minAllowableSelectionCount\":{\"value\":1},\"choices\":{\"value\":[\"

    <\\/oppia-noninteractive-math>
    <\\/p>\",\"

    3\\/7<\\/p>\",\"

    <\\/oppia-noninteractive-math>
    <\\/p>\",\"

    2\\/3<\\/p>\"]}},\"confirmed_unclassified_answers\":[],\"id\":\"ItemSelectionInput\",\"hints\":[{\"hint_content\":{\"content_id\":\"hint_1\",\"html\":\"

    Note that you can select more than one correct answer.<\\/p>\"}},{\"hint_content\":{\"content_id\":\"hint_2\",\"html\":\"

    Remember, the denominator comes at the bottom<\\/em> of the fraction.\\u00a0If the fraction is written as \\\"x\\/y\\\", then the denominator is to the right of the \\\"\\/\\\".\\u00a0For example:<\\/p>

    \\u00a0<\\/p>

    <\\/p>

    • In\\u00a0<\\/oppia-noninteractive-math>, the denominator is 7.<\\/li>
    • In 5\\/6, the denominator is 6.
      <\\/li><\\/ul>

      <\\/p>\"}}]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":173702,\"needs_update\":false,\"filename\":\"content-es-su8bb5y8bcg.mp3\"},\"hi-en\":{\"file_size_bytes\":103155,\"needs_update\":false,\"filename\":\"content-hi-en-4r92atn0m8t4ptaudg0pwlv7vi.mp3\"}},\"feedback_4\":{},\"feedback_2\":{},\"feedback_3\":{},\"feedback_1\":{},\"hint_1\":{},\"hint_2\":{},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

      Question 3<\\/strong>: Which of these fractions have \\\"3\\\" as the denominator?<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"feedback_4\":{},\"feedback_2\":{},\"feedback_3\":{},\"feedback_1\":{},\"hint_1\":{},\"hint_2\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Remedial - Numerator and Denominator\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"\"},\"dest\":\"Remedial 2 - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"buttonText\":{\"value\":\"Continue\"}},\"confirmed_unclassified_answers\":[],\"id\":\"Continue\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"hi-en\":{\"file_size_bytes\":358563,\"needs_update\":false,\"filename\":\"content-hi-en-km3kt185cen.mp3\"}},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

      \\\"Could we go over this again, step by step?\\\" asked Matthew.<\\/p>

      \\\"Sure!\\\" said Mr. Baker.\\u00a0\\\"A fraction consists of two parts: a numerator<\\/strong>\\u00a0and a denominator<\\/strong>. We usually start by thinking about the denominator first. Let's walk through an example:<\\/p><\\/oppia-noninteractive-image>

      \\\"The\\u00a0denominator counts how many equal\\u00a0parts the whole<\\/em> circle is divided into. In this case, there are 10 equal parts, so the denominator is 10. We always write the denominator on the bottom<\\/em>, like this:<\\/p><\\/oppia-noninteractive-image>

      \\\"Does that make sense? If so, we'll talk about the numerator next.\\\"<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Q1 on N and D\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_1\",\"html\":\"

      Not quite. Let's look at it again.<\\/p>\"},\"dest\":\"Remedial - Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":0}}],\"tagged_misconception_id\":null},{\"outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"feedback_2\",\"html\":\"

      Great! Let's try another.<\\/p>\"},\"dest\":\"Q2 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"training_data\":[],\"rule_specs\":[{\"rule_type\":\"Equals\",\"inputs\":{\"x\":1}}],\"tagged_misconception_id\":null}],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"

      That's OK. Let's look at it again.<\\/p>\"},\"dest\":\"Numerator and Denominator\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"choices\":{\"value\":[\"

      The number of pieces of cake I want.<\\/p>\",\"

      The number of pieces the whole cake is cut into.<\\/p>\",\"

      I don't remember!<\\/p>\"]}},\"confirmed_unclassified_answers\":[],\"id\":\"MultipleChoiceInput\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":377246,\"needs_update\":false,\"filename\":\"content-es-8alct3xmc3g.mp3\"},\"hi-en\":{\"file_size_bytes\":214793,\"needs_update\":false,\"filename\":\"content-hi-en-isfsyfm9v9xt8rcesqp4g3nmi.mp3\"}},\"feedback_2\":{},\"feedback_1\":{},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

      \\\"OK!\\\" said Mr. Baker. \\\"Here's a question for you.\\\"
      <\\/p>

      Question 1<\\/strong>: If we talk about wanting <\\/oppia-noninteractive-math> of a cake, what does the 7 represent?<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"feedback_2\":{},\"feedback_1\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Problem\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"\"},\"dest\":\"Into the Bakery\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"buttonText\":{\"value\":\"Continue\"}},\"confirmed_unclassified_answers\":[],\"id\":\"Continue\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":564528,\"needs_update\":false,\"filename\":\"content-es-l59b9b93uf.mp3\"},\"hi-en\":{\"file_size_bytes\":456800,\"needs_update\":false,\"filename\":\"content-hi-en-esaliyf5pdj0ma1n2mcjif6r.mp3\"}},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

      Matthew had a problem. His Aunt Tina was visiting that afternoon, and he had nothing for her to eat!<\\/p><\\/oppia-noninteractive-image>

      \\u201cI could buy some cake!\\u201d Matthew thought. He had passed a bakery earlier that day which had a very yummy-looking chocolate cake in the window. That would be perfect!<\\/p><\\/oppia-noninteractive-image>

      \\u00a0<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Remedial 2 - Numerator and Denominator\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"\"},\"dest\":\"Q1 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"buttonText\":{\"value\":\"Continue\"}},\"confirmed_unclassified_answers\":[],\"id\":\"Continue\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"hi-en\":{\"file_size_bytes\":369201,\"needs_update\":false,\"filename\":\"content-hi-en-l3c9btyxw3l.mp3\"}},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

      \\\"To complete the fraction, let's take another look at our picture,\\\" said Mr. Baker.<\\/p><\\/oppia-noninteractive-image>

      \\\"The\\u00a0numerator<\\/em>\\u00a0counts\\u00a0how many parts we want. 3 of the 10 pieces are shaded, so 3 is our numerator. This means that the fraction representing the shaded part of the circle is 3\\/10. Does that make sense?\\\"<\\/p><\\/oppia-noninteractive-image>

      When Matthew felt he understood, he nodded.<\\/p>

      \\\"OK,\\\" said Mr. Baker. \\\"It's good to practice this until you're sure you know it, so let's try some of those questions again!\\\"
      <\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false},\"Numerator and Denominator\":{\"param_changes\":[],\"interaction\":{\"solution\":null,\"answer_groups\":[],\"default_outcome\":{\"param_changes\":[],\"feedback\":{\"content_id\":\"default_outcome\",\"html\":\"\"},\"dest\":\"Q1 on N and D\",\"refresher_exploration_id\":null,\"missing_prerequisite_skill_id\":null,\"labelled_as_correct\":false},\"customization_args\":{\"buttonText\":{\"value\":\"CONTINUE\"}},\"confirmed_unclassified_answers\":[],\"id\":\"Continue\",\"hints\":[]},\"recorded_voiceovers\":{\"voiceovers_mapping\":{\"content\":{\"es\":{\"file_size_bytes\":1506261,\"needs_update\":false,\"filename\":\"content-es-hd01d0f2u0d.mp3\"},\"hi-en\":{\"file_size_bytes\":993873,\"needs_update\":false,\"filename\":\"content-hi-en-1qad0l4oh9hzynrur85nx9a4i.mp3\"}},\"default_outcome\":{}}},\"classifier_model_id\":null,\"content\":{\"content_id\":\"content\",\"html\":\"

      Matthew looked confused.
      <\\/p>

      \\\"Ah,\\\" said Mr. Baker. \\\"That just means how much of the whole thing do you want. Here, I\\u2019ll show you.\\u201d He picked up a napkin and a pencil. \\u201cLook,\\u201d he said, starting to draw.<\\/p><\\/oppia-noninteractive-image>

      \\ufeff
      <\\/p>

      \\u201cHere\\u2019s a cake. Pretend it\\u2019s divided into five equal parts, OK?\\u201d Then he filled in two of the parts.<\\/p><\\/oppia-noninteractive-image>

      \\\"You can call that two-fifths<\\/em>. And you write it like this:\\u00a0<\\/oppia-noninteractive-math><\\/strong>.\\u00a0It means: the whole cake is cut up into five<\\/em> equal pieces (that\\u2019s the number below the line) and you want two<\\/em> of those pieces (the number on top). We call the top number the\\u00a0numerator<\\/strong>, and the bottom number the\\u00a0denominator<\\/strong>.\\\"
      <\\/p><\\/oppia-noninteractive-image>

      \\\"Now let's see if you understand that!\\\" said Mr. Baker. \\\"Are you ready?\\\"<\\/p>\"},\"written_translations\":{\"translations_mapping\":{\"content\":{},\"default_outcome\":{}}},\"solicit_answer_details\":false}},\"param_specs\":{},\"language_code\":\"en\",\"init_state_name\":\"Introduction\",\"correctness_feedback_enabled\":false},\"is_moderator\":false,\"can_edit\":false,\"auto_tts_enabled\":true,\"exploration_id\":\"DIWZiVgs0km-\",\"session_id\":\"MJfwOrurV-vJoj2IA6Wwqvuo\",\"state_classifier_mapping\":{},\"is_super_admin\":false,\"additional_angular_modules\":[],\"iframed\":false,\"is_admin\":false,\"correctness_feedback_enabled\":false,\"version\":56,\"record_playthrough_probability\":0.2,\"is_topic_manager\":false,\"preferred_audio_language_code\":null,\"is_logged_in\":false}" + } + + fun getFakeExploration(): GaeExplorationContainer { + val moshi = Moshi.Builder().build() + val adapter: JsonAdapter = + moshi.adapter(GaeExplorationContainer::class.java) + val fakeGaeExplorationContainer = adapter.fromJson(EXPLORATION_SERVICE_RESPONSE) + + return fakeGaeExplorationContainer!! + } +} + From c6292d8ca6f580f2a9c573171f68316204ab96b9 Mon Sep 17 00:00:00 2001 From: veena Date: Fri, 13 Sep 2019 18:44:39 +0530 Subject: [PATCH 03/24] created dummy content list --- app/build.gradle | 5 +- app/src/main/AndroidManifest.xml | 13 ++- .../app/player/content/ContentCardAdapter.kt | 61 ++++++++++ .../app/player/content/ContentListFragment.kt | 110 ++++++++++++++++++ .../ExplorationActivityController.kt | 5 +- .../ExplorationFragmentController.kt | 2 + .../org/oppia/app/utility/URlImageParser.kt | 43 +++++++ app/src/main/res/drawable/bg_blue_card.xml | 11 ++ .../main/res/layout/content_card_items.xml | 15 +++ .../main/res/layout/content_list_fragment.xml | 37 ++++++ app/src/main/res/values/strings.xml | 3 + .../backends/gae/model/GaeSubtitledHtml.kt | 4 +- 12 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/org/oppia/app/player/content/ContentCardAdapter.kt create mode 100644 app/src/main/java/org/oppia/app/player/content/ContentListFragment.kt create mode 100644 app/src/main/java/org/oppia/app/utility/URlImageParser.kt create mode 100644 app/src/main/res/drawable/bg_blue_card.xml create mode 100644 app/src/main/res/layout/content_card_items.xml create mode 100644 app/src/main/res/layout/content_list_fragment.xml diff --git a/app/build.gradle b/app/build.gradle index 64ea16800a2..3f8d5e3a619 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -64,8 +64,11 @@ dependencies { 'com.google.dagger:dagger:2.24', "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version", "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1", - "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1" + "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1", + 'androidx.recyclerview:recyclerview:1.0.0', + 'com.github.bumptech.glide:glide:4.9.0' ) + implementation 'androidx.legacy:legacy-support-v4:1.0.0' testImplementation( 'androidx.test:core:1.2.0', 'androidx.test.espresso:espresso-core:3.2.0', diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c632728593b..89235fbfa9e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,8 +11,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/OppiaTheme"> - - + @@ -22,5 +21,15 @@ + + + + + + + + + + diff --git a/app/src/main/java/org/oppia/app/player/content/ContentCardAdapter.kt b/app/src/main/java/org/oppia/app/player/content/ContentCardAdapter.kt new file mode 100644 index 00000000000..a5fb1fb7026 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/content/ContentCardAdapter.kt @@ -0,0 +1,61 @@ +package org.oppia.app.player.content + +import android.content.Context +import android.text.Html +import android.text.Spannable +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import org.oppia.app.R +import org.oppia.app.utility.URLImageParser +import org.oppia.data.backends.gae.model.GaeSubtitledHtml + +import java.util.ArrayList + +class ContentCardAdapter(internal var context: Context, contentList: List) : + RecyclerView.Adapter() { + internal var contentList: List = ArrayList() + + init { + // TODO Auto-generated constructor stub + this.contentList = contentList + + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { + // System.out.println("hiiiiii"+shopList.get(0).getShop_name()); + val itemView = LayoutInflater.from(parent.context) + .inflate(R.layout.content_card_items, parent, false) + + return MyViewHolder(itemView) + } + + override fun onBindViewHolder(holder: MyViewHolder, position: Int) { + + val imageGetter = URLImageParser(holder.tvContents, context) + val html: Spannable + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + html = Html.fromHtml(contentList[position].html, Html.FROM_HTML_MODE_LEGACY, imageGetter, null) as Spannable + } else { + html = Html.fromHtml(contentList[position].html, imageGetter, null) as Spannable + } + holder.tvContents.text = html + } + + inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { + + internal var tvContents: TextView + + init { + tvContents = view.findViewById(R.id.tvContents) + + } + } + + override fun getItemCount(): Int { + return contentList.size + } + +} diff --git a/app/src/main/java/org/oppia/app/player/content/ContentListFragment.kt b/app/src/main/java/org/oppia/app/player/content/ContentListFragment.kt new file mode 100644 index 00000000000..6716e5d8237 --- /dev/null +++ b/app/src/main/java/org/oppia/app/player/content/ContentListFragment.kt @@ -0,0 +1,110 @@ +package org.oppia.app.player.content + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button + +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import org.oppia.app.R +import org.oppia.data.backends.gae.model.GaeSubtitledHtml + +import java.util.ArrayList + +/** + */ +class ContentListFragment : Fragment() { + + // TODO: Rename and change types of parameters + private var mParam1: String? = null + private var mParam2: String? = null + + var mLayoutManager: LinearLayoutManager? = null + + var rvContentCard: RecyclerView? = null + + var btnBack: Button? = null + var btnContinue: Button? = null + + var adapter: ContentCardAdapter? = null + + var contentList: MutableList = ArrayList() + var dummyList: MutableList = ArrayList() + + var btnCount = 0; + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Inflate the layout for this fragment + val view = inflater.inflate(R.layout.content_list_fragment, container, false) + + rvContentCard = view.findViewById(R.id.rvContentCard) + btnContinue = view.findViewById(R.id.btnContinue) + btnBack = view.findViewById(R.id.btnBack) + + initviews() + + return view + } + + private fun initviews() { + + mLayoutManager = LinearLayoutManager(activity) + rvContentCard!!.layoutManager = mLayoutManager + + dummyList.add(createDummyContentData()) + dummyList.add(createDummyProblem()) + dummyList.add(createDummyQ1onNandD()) + + contentList.add(createDummyContentData()) + + + adapter = ContentCardAdapter(requireContext(), contentList) + rvContentCard!!.adapter = adapter + + btnContinue!!.setOnClickListener { + btnCount++; + btnBack!!.visibility = View.VISIBLE; + contentList.clear() + contentList.add(dummyList.get(btnCount)) + adapter!!.notifyDataSetChanged(); + } + btnBack!!.setOnClickListener { + btnCount--; + if(btnCount==0) + btnBack!!.visibility = View.GONE; + contentList.clear() + contentList.add(dummyList.get(btnCount)) + adapter!!.notifyDataSetChanged(); + } + } + + private fun createDummyContentData(): GaeSubtitledHtml { + + return GaeSubtitledHtml( + "content", + "\u003cp\u003eMeet Matthew!\u003c/p\u003e\u003coppia-noninteractive-image alt-with-value=\"\u0026amp;quot;Matthew.\u0026amp;quot;\" caption-with-value=\"\u0026amp;quot;\\\u0026amp;quot;Hi!\\\u0026amp;quot;\u0026amp;quot;\" filepath-with-value=\"\u0026amp;quot;hello_height_253_width_108.png\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-image\u003e\u003cp\u003eMatthew is a typical young man: he likes friends, sports, and eating cake! He also likes learning new things. We\u2019ll follow Matthew as he learns about fractions and how to use them.\u003c/p\u003e\u003cp\u003eYou should know the following before continuing:\u003c/p\u003e\u003cul\u003e\u003cli\u003eThe counting numbers (1, 2, 3, 4, 5, ...)" + "\u003c/li\u003e\u003cli\u003eHow to add, subtract, multiply, and divide these numbers\u003c/li\u003e\u003cli\u003eHow to tell whether a number is bigger than another.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eYou should also get some\u00a0paper and a pen or pencil\u00a0to write with, and find a quiet place to work. Be sure to take your time and go through the story at your own pace. Understanding is more important than speed!\u003cbr\u003e\u003c/p\u003e\u003cp\u003eReady? Click\u00a0\u003cstrong\u003eContinue\u003c/strong\u003e\u00a0to get started!\u003c/p\u003e" + ) + } + + private fun createDummyProblem(): GaeSubtitledHtml { + + return GaeSubtitledHtml( + "problem", + "\u003cp\u003eMatthew had a problem. His Aunt Tina was visiting that afternoon, and he had nothing for her to eat!\u003c/p\u003e\u003coppia-noninteractive-image alt-with-value=\"\u0026amp;quot;Matthew is feeling Sad.\u0026amp;quot;\" caption-with-value=\"\u0026amp;quot;\u0026amp;quot;\" filepath-with-value=\"\u0026amp;quot;Sad_small_height_142_width_61.png\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-image\u003e\u003cp\u003e\u201cI could buy some cake!\u201d Matthew thought. He had passed a bakery earlier that day which had a very yummy-looking chocolate cake in the window. That would be perfect!\u003c/p\u003e\u003coppia-noninteractive-image alt-with-value=\"\u0026amp;quot;A bakery shop\u0026amp;quot;\" caption-with-value=\"\u0026amp;quot;\u0026amp;quot;\" filepath-with-value=\"\u0026amp;quot;img_20170804_023625_karrj6fyko_height_350_width_250.png\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-image\u003e\u003cp\u003e\u00a0\u003c/p\u003e" + ); + + } + + private fun createDummyQ1onNandD(): GaeSubtitledHtml { + + return GaeSubtitledHtml( + "Q1 on N and D", + "\u003cp\u003eMatthew looked confused.\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\"Ah,\" said Mr. Baker. \"That just means how much of the whole thing do you want. Here, I\u2019ll show you.\u201d He picked up a napkin and a pencil. \u201cLook,\u201d he said, starting to draw.\u003c/p\u003e\u003coppia-noninteractive-image alt-with-value=\"\u0026amp;quot;Sketch of circle divided into fifths.\u0026amp;quot;\" caption-with-value=\"\u0026amp;quot;\u0026amp;quot;\" filepath-with-value=\"\u0026amp;quot;fifthsC_height_172_width_216.png\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-image\u003e\u003cp\u003e\ufeff\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u201cHere\u2019s a cake. Pretend it\u2019s divided into five equal parts, OK?\u201d Then he filled in two of the parts.\u003c/p\u003e\u003coppia-noninteractive-image alt-with-value=\"\u0026amp;quot;Sketch of circle with 2/5 shaded.\u0026amp;quot;\" caption-with-value=\"\u0026amp;quot;\u0026amp;quot;\" filepath-with-value=\"\u0026amp;quot;shaded_fifthsC_height_172_width_216.png\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-image\u003e\u003cp\u003e\"You can call that \u003cem\u003etwo-fifths\u003c/em\u003e. And you write it like this:\u00a0\u003cstrong\u003e\u003coppia-noninteractive-math raw_latex-with-value=\"\u0026amp;quot;\\\\frac{2}{5}\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-math\u003e\u003c/strong\u003e.\u00a0It means: the whole cake is cut up into \u003cem\u003efive\u003c/em\u003e equal pieces (that\u2019s the number below the line) and you want \u003cem\u003etwo\u003c/em\u003e of those pieces (the number on top). We call the top number the\u00a0\u003cstrong\u003enumerator\u003c/strong\u003e, and the bottom number the\u00a0\u003cstrong\u003edenominator\u003c/strong\u003e.\"\u003cbr\u003e\u003c/p\u003e\u003coppia-noninteractive-image alt-with-value=\"\u0026amp;quot;numerator and denominator diagram\u0026amp;quot;\" caption-with-value=\"\u0026amp;quot;\u0026amp;quot;\" filepath-with-value=\"\u0026amp;quot;NDb_height_151_width_600.png\u0026amp;quot;\"\u003e\u003c/oppia-noninteractive-image\u003e\u003cp\u003e\"Now let's see if you understand that!\" said Mr. Baker. \"Are you ready?\"\u003c/p\u003e"); + + } +} diff --git a/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt b/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt index 1d8ad338bf6..80e3fe75ee5 100755 --- a/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt +++ b/app/src/main/java/org/oppia/app/player/exploration/ExplorationActivityController.kt @@ -1,8 +1,11 @@ package org.oppia.app.player.exploration +import android.media.SubtitleData import androidx.appcompat.app.AppCompatActivity import org.oppia.app.R import org.oppia.app.activity.ActivityScope +import org.oppia.app.player.content.ContentListFragment +import org.oppia.data.backends.gae.model.GaeSubtitledHtml import javax.inject.Inject /** The controller for [ExplorationActivity]. */ @@ -12,7 +15,7 @@ class ExplorationActivityController @Inject constructor(private val activity: Ap activity.setContentView(R.layout.exploration_activity) activity.supportFragmentManager.beginTransaction().add( R.id.exploration_fragment_placeholder, - ExplorationFragment() + ContentListFragment() ).commitNow() } } diff --git a/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt b/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt index 2d3a6386703..9dd78c5c95a 100755 --- a/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt +++ b/app/src/main/java/org/oppia/app/player/exploration/ExplorationFragmentController.kt @@ -4,8 +4,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import org.oppia.app.R import org.oppia.app.databinding.ExplorationFragmentBinding import org.oppia.app.fragment.FragmentScope +import org.oppia.app.home.HomeFragment import javax.inject.Inject /** The controller for [ExplorationFragment]. */ diff --git a/app/src/main/java/org/oppia/app/utility/URlImageParser.kt b/app/src/main/java/org/oppia/app/utility/URlImageParser.kt new file mode 100644 index 00000000000..0844194d254 --- /dev/null +++ b/app/src/main/java/org/oppia/app/utility/URlImageParser.kt @@ -0,0 +1,43 @@ +package org.oppia.app.utility; + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.LevelListDrawable +import android.text.Html +import android.widget.TextView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.SimpleTarget +import com.bumptech.glide.request.transition.Transition +import java.net.URL + +/** */ +open class URLImageParser(internal var mTv: TextView, internal var mContext: Context) : Html.ImageGetter { + + override fun getDrawable(source: String): Drawable { + val drawable = LevelListDrawable() + Glide.with(mContext) + .asBitmap() + .load(URL(source)) + .apply( RequestOptions().override(100, 100)) //This is important + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .into(object : SimpleTarget() { + override fun onResourceReady(resource: Bitmap, transition: Transition?) { + if (resource != null) { + val bitmapDrawable = BitmapDrawable(resource) + drawable.addLevel(1, 1, bitmapDrawable) + drawable.setBounds(0, 0, resource.width, resource.height) + drawable.level = 1 + mTv.invalidate() + mTv.text = mTv.text + + } + } + }); + return drawable + } + +} diff --git a/app/src/main/res/drawable/bg_blue_card.xml b/app/src/main/res/drawable/bg_blue_card.xml new file mode 100644 index 00000000000..9e0bfca3ffa --- /dev/null +++ b/app/src/main/res/drawable/bg_blue_card.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/main/res/layout/content_card_items.xml b/app/src/main/res/layout/content_card_items.xml new file mode 100644 index 00000000000..33539a5de1e --- /dev/null +++ b/app/src/main/res/layout/content_card_items.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/app/src/main/res/layout/content_list_fragment.xml b/app/src/main/res/layout/content_list_fragment.xml new file mode 100644 index 00000000000..67734b9e4d5 --- /dev/null +++ b/app/src/main/res/layout/content_list_fragment.xml @@ -0,0 +1,37 @@ + + + + + +