Red
", + "Blue
", + "Green
" + ] + }, + "rule_type": "Equals" + } + ], + "tagged_skill_misconception_id": null + }, + { + "outcome": { + "dest": "ItemSelectionMulti", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_2", + "html": "'Yellow' is considered a primary color in the RYB color spectrum, but that doesn't correspond to light. Try again!
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": [ + "Yellow
" + ] + }, + "rule_type": "ContainsAtLeastOneOf" + } + ], + "tagged_skill_misconception_id": null + } + ], + "customization_args": { + "choices": { + "value": [ + "Red
", + "Yellow
", + "Green
", + "Blue
", + "Orange
", + "Purple
" + ] + }, + "minAllowableSelectionCount": { + "value": 1 + }, + "maxAllowableSelectionCount": { + "value": 3 + } + }, + "id": "ItemSelectionInput", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "ItemSelectionMulti", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "That's not quite right. Try again.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "feedback_2": {}, + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_2": {}, + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "What are the primary colors of light?
" + } + }, + "MultipleChoice": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [ + { + "outcome": { + "dest": "ItemSelectionMinOne", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_1", + "html": "Correct! Eagles can sustain flight.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": 2 + }, + "rule_type": "Equals" + } + ], + "tagged_skill_misconception_id": null + } + ], + "customization_args": { + "choices": { + "value": [ + "Penguin
", + "Chicken
", + "Eagle
" + ] + } + }, + "id": "MultipleChoiceInput", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "MultipleChoice", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "Try again.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "Which bird can sustain flight for long periods of time?
" + } + }, + "Fractions": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [ + { + "outcome": { + "dest": "MultipleChoice", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_1", + "html": "Correct!
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "f": { + "wholeNumber": 0, + "denominator": 2, + "numerator": 1, + "isNegative": false + } + }, + "rule_type": "IsExactlyEqualTo" + } + ], + "tagged_skill_misconception_id": null + } + ], + "customization_args": { + "allowNonzeroIntegerPart": { + "value": true + }, + "customPlaceholder": { + "value": "" + }, + "allowImproperFraction": { + "value": true + }, + "requireSimplestForm": { + "value": false + } + }, + "id": "FractionInput", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "Fractions", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "That answer isn't correct. Try again.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "What fraction represents half of something?
" + } + }, + "Continue": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [], + "customization_args": { + "buttonText": { + "value": "Continue" + } + }, + "id": "Continue", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "Fractions", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "Test exploration with interactions.
" + } + }, + "NumberInput": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [ + { + "outcome": { + "dest": "Text", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_1", + "html": "Correct!
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": 121 + }, + "rule_type": "Equals" + } + ], + "tagged_skill_misconception_id": null + }, + { + "outcome": { + "dest": "NumberInput", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_2", + "html": "Not quite. It's actually larger than that. Try again.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": 121 + }, + "rule_type": "IsLessThan" + } + ], + "tagged_skill_misconception_id": null + }, + { + "outcome": { + "dest": "NumberInput", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_3", + "html": "Not quite. It's less than that.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": 121 + }, + "rule_type": "IsGreaterThan" + } + ], + "tagged_skill_misconception_id": null + } + ], + "customization_args": {}, + "id": "NumericInput", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "NumberInput", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "Something went wrong. The answer is 121--try again.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "feedback_2": {}, + "feedback_3": {}, + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_2": {}, + "feedback_3": {}, + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "What is 11 times 11?
" + } + }, + "Text": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [ + { + "outcome": { + "dest": "End", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_1", + "html": "Correct!
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": "finnish" + }, + "rule_type": "Equals" + } + ], + "tagged_skill_misconception_id": null + } + ], + "customization_args": { + "rows": { + "value": 1 + }, + "placeholder": { + "value": "" + } + }, + "id": "TextInput", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "Text", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "Not quite. Try again (or maybe use a search engine).
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "In which language does Oppia mean 'to learn'?
" + } + }, + "ItemSelectionMinOne": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [ + { + "outcome": { + "dest": "ItemSelectionMulti", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "feedback_1", + "html": "Correct!
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + }, + "training_data": [], + "rule_specs": [ + { + "inputs": { + "x": [ + "Green
" + ] + }, + "rule_type": "Equals" + } + ], + "tagged_skill_misconception_id": null + } + ], + "customization_args": { + "choices": { + "value": [ + "Green
", + "Red
", + "Blue
" + ] + }, + "minAllowableSelectionCount": { + "value": 1 + }, + "maxAllowableSelectionCount": { + "value": 1 + } + }, + "id": "ItemSelectionInput", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": { + "dest": "ItemSelectionMinOne", + "labelled_as_correct": false, + "param_changes": [], + "feedback": { + "content_id": "default_outcome", + "html": "Not quite. Try again.
" + }, + "missing_prerequisite_skill_id": null, + "refresher_exploration_id": null + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "content": { + "content_id": "content", + "html": "What color does the 'G' in 'RGB' correspond to?
" + } + }, + "End": { + "param_changes": [], + "classifier_model_id": null, + "solicit_answer_details": false, + "interaction": { + "solution": null, + "answer_groups": [], + "customization_args": { + "recommendedExplorationIds": { + "value": [] + } + }, + "id": "EndExploration", + "hints": [], + "confirmed_unclassified_answers": [], + "default_outcome": null + }, + "written_translations": { + "translations_mapping": { + "content": {} + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {} + } + }, + "content": { + "content_id": "content", + "html": "Congratulations, you have finished!" + } + } + }, + "correctness_feedback_enabled": false, + "objective": "Demonstrate core interactions used in the Oppia prototype.", + "init_state_name": "Continue" +} diff --git a/domain/src/main/assets/welcome.json b/domain/src/main/assets/welcome.json index 157a4fb44a7..7030ee04c9e 100644 --- a/domain/src/main/assets/welcome.json +++ b/domain/src/main/assets/welcome.json @@ -553,4 +553,4 @@ "states_schema_version": 30, "tags": [], "title": "Welcome to Oppia!" -} \ No newline at end of file +} diff --git a/domain/src/main/java/org/oppia/domain/audio/AudioPlayerController.kt b/domain/src/main/java/org/oppia/domain/audio/AudioPlayerController.kt index edac18f5c4c..bb396f5aaa5 100644 --- a/domain/src/main/java/org/oppia/domain/audio/AudioPlayerController.kt +++ b/domain/src/main/java/org/oppia/domain/audio/AudioPlayerController.kt @@ -1,10 +1,7 @@ package org.oppia.domain.audio -import android.content.Context import android.media.MediaPlayer -import android.net.Uri import androidx.annotation.VisibleForTesting -import androidx.fragment.app.Fragment import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher diff --git a/domain/src/main/java/org/oppia/domain/classify/AnswerClassificationController.kt b/domain/src/main/java/org/oppia/domain/classify/AnswerClassificationController.kt index f2f734da486..160b4af92e6 100644 --- a/domain/src/main/java/org/oppia/domain/classify/AnswerClassificationController.kt +++ b/domain/src/main/java/org/oppia/domain/classify/AnswerClassificationController.kt @@ -4,7 +4,6 @@ import org.oppia.app.model.AnswerGroup import org.oppia.app.model.Interaction import org.oppia.app.model.InteractionObject import org.oppia.app.model.Outcome -import java.lang.IllegalStateException import javax.inject.Inject // TODO(#59): Restrict the visibility of this class to only other controllers. diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt index e7f798f69d7..11cf2160f4b 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.fractioninput import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt index 2374f752504..74d0b5a86b7 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.fractioninput import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.approximatelyEquals import org.oppia.domain.util.toFloat import org.oppia.domain.util.toSimplestForm diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt index bbd16b8b619..de68cd6bd37 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.fractioninput import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.approximatelyEquals import org.oppia.domain.util.toFloat import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt index ff0e73e6992..258b47fd858 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.fractioninput import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt index 48168244325..b0ed1dc7990 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.fractioninput import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.toFloat import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt index 4833dd53279..b95bf63b09f 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.fractioninput import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.toFloat import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt index b85a2de1672..a2620eeb152 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.itemselectioninput import org.oppia.app.model.InteractionObject import org.oppia.app.model.StringList import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt index de2e7a100ac..98eac18e758 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.itemselectioninput import org.oppia.app.model.InteractionObject import org.oppia.app.model.StringList import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt index c789313c626..b7085c4d18c 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.itemselectioninput import org.oppia.app.model.InteractionObject import org.oppia.app.model.StringList import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt index 74f6db2c4a1..47d47a1c18b 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.itemselectioninput import org.oppia.app.model.InteractionObject import org.oppia.app.model.StringList import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider.kt index 3396b00cd30..5842a02581c 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.multiplechoiceinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt index b427217bf7e..7d44f1e708f 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt @@ -4,8 +4,8 @@ import org.oppia.app.model.Fraction import org.oppia.app.model.InteractionObject import org.oppia.app.model.NumberWithUnits import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.approximatelyEquals import javax.inject.Inject @@ -42,7 +42,7 @@ internal class NumberWithUnitsIsEqualToRuleClassifierProvider @Inject constructo } } - private fun realMatches(answer: Float, input: Float): Boolean { + private fun realMatches(answer: Double, input: Double): Boolean { return input.approximatelyEquals(answer) } diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt index 5bc71da1957..1fd0727ff3c 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt @@ -3,8 +3,8 @@ package org.oppia.domain.classify.rules.numberwithunits import org.oppia.app.model.InteractionObject import org.oppia.app.model.NumberWithUnits import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.approximatelyEquals import org.oppia.domain.util.toFloat import javax.inject.Inject @@ -35,10 +35,10 @@ internal class NumberWithUnitsIsEquivalentToRuleClassifierProvider @Inject const return extractRealValue(input).approximatelyEquals(extractRealValue(answer)) } - private fun extractRealValue(number: NumberWithUnits): Float { + private fun extractRealValue(number: NumberWithUnits): Double { return when (number.numberTypeCase) { NumberWithUnits.NumberTypeCase.REAL -> number.real - NumberWithUnits.NumberTypeCase.FRACTION -> number.fraction.toFloat() + NumberWithUnits.NumberTypeCase.FRACTION -> number.fraction.toFloat().toDouble() else -> throw IllegalArgumentException("Invalid number type: ${number.numberTypeCase.name}") } } diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputEqualsRuleClassifierProvider.kt index b732043ddf7..b78aec022a6 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputEqualsRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.numericinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.approximatelyEquals import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt index a984e2f2698..9d34ce0d960 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.numericinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt index d030bbc15c4..2e0d9e085e2 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.numericinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt index edbf7cfdacc..ea88f8b1ca5 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.numericinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt index 33b982c7798..5916333025c 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.numericinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import javax.inject.Inject /** diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt index 3c66af19b42..204c2c0b629 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.textinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.normalizeWhitespace import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputContainsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputContainsRuleClassifierProvider.kt index 429e120522d..9036a7b4039 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputContainsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputContainsRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.textinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.normalizeWhitespace import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputEqualsRuleClassifierProvider.kt index cb85790cd17..cc76d612495 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputEqualsRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.textinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.normalizeWhitespace import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt index 26753c7cd85..aed9b4b372c 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.textinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.normalizeWhitespace import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt index 7a8d73fbefe..97f00ced135 100644 --- a/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt @@ -2,8 +2,8 @@ package org.oppia.domain.classify.rules.textinput import org.oppia.app.model.InteractionObject import org.oppia.domain.classify.RuleClassifier -import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.classify.rules.GenericRuleClassifier +import org.oppia.domain.classify.rules.RuleClassifierProvider import org.oppia.domain.util.normalizeWhitespace import javax.inject.Inject diff --git a/domain/src/main/java/org/oppia/domain/exploration/ExplorationRetriever.kt b/domain/src/main/java/org/oppia/domain/exploration/ExplorationRetriever.kt index ed000e541ca..4dcf89c3bdf 100644 --- a/domain/src/main/java/org/oppia/domain/exploration/ExplorationRetriever.kt +++ b/domain/src/main/java/org/oppia/domain/exploration/ExplorationRetriever.kt @@ -12,6 +12,7 @@ import javax.inject.Inject const val TEST_EXPLORATION_ID_5 = "DIWZiVgs0km-" const val TEST_EXPLORATION_ID_6 = "test_exp_id_6" +const val TEST_EXPLORATION_ID_30 = "30" const val TEST_EXPLORATION_ID_7 = "test_exp_id_7" // TODO(#59): Make this class inaccessible outside of the domain package except for tests. UI code should not be allowed @@ -28,6 +29,7 @@ class ExplorationRetriever @Inject constructor( return when (explorationId) { TEST_EXPLORATION_ID_5 -> loadExplorationFromAsset("welcome.json") TEST_EXPLORATION_ID_6 -> loadExplorationFromAsset("about_oppia.json") + TEST_EXPLORATION_ID_30 -> loadExplorationFromAsset("prototype_exploration.json") TEST_EXPLORATION_ID_7 -> loadExplorationFromAsset("oppia_exploration.json") FRACTIONS_EXPLORATION_ID_0 -> loadExplorationFromAsset("fractions_exploration0.json") FRACTIONS_EXPLORATION_ID_1 -> loadExplorationFromAsset("fractions_exploration1.json") @@ -62,5 +64,4 @@ class ExplorationRetriever @Inject constructor( } return statesMap } - } diff --git a/domain/src/main/java/org/oppia/domain/topic/StoryProgressController.kt b/domain/src/main/java/org/oppia/domain/topic/StoryProgressController.kt index 368a61314c6..5abd210d5c5 100644 --- a/domain/src/main/java/org/oppia/domain/topic/StoryProgressController.kt +++ b/domain/src/main/java/org/oppia/domain/topic/StoryProgressController.kt @@ -3,14 +3,13 @@ package org.oppia.domain.topic import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import org.json.JSONArray -import javax.inject.Inject -import javax.inject.Singleton import org.oppia.app.model.ChapterPlayState import org.oppia.app.model.ChapterProgress import org.oppia.app.model.StoryProgress -import org.oppia.app.model.StorySummary import org.oppia.domain.util.JsonAssetRetriever import org.oppia.util.data.AsyncResult +import javax.inject.Inject +import javax.inject.Singleton const val TEST_STORY_ID_0 = "test_story_id_0" const val TEST_STORY_ID_1 = "test_story_id_1" diff --git a/domain/src/main/java/org/oppia/domain/topic/TopicController.kt b/domain/src/main/java/org/oppia/domain/topic/TopicController.kt index 81c5395fd97..0d2a250a32d 100644 --- a/domain/src/main/java/org/oppia/domain/topic/TopicController.kt +++ b/domain/src/main/java/org/oppia/domain/topic/TopicController.kt @@ -5,9 +5,6 @@ import androidx.lifecycle.MutableLiveData import org.json.JSONArray import org.json.JSONObject import org.oppia.app.model.ChapterPlayState -import java.lang.IllegalArgumentException -import javax.inject.Inject -import javax.inject.Singleton import org.oppia.app.model.ChapterSummary import org.oppia.app.model.ConceptCard import org.oppia.app.model.LessonThumbnail @@ -21,11 +18,14 @@ import org.oppia.app.model.Translation import org.oppia.app.model.TranslationMapping import org.oppia.app.model.Voiceover import org.oppia.app.model.VoiceoverMapping +import org.oppia.domain.exploration.TEST_EXPLORATION_ID_30 import org.oppia.domain.util.JsonAssetRetriever import org.oppia.domain.util.StateRetriever import org.oppia.util.data.AsyncResult import org.oppia.util.data.DataProvider import org.oppia.util.data.DataProviders +import javax.inject.Inject +import javax.inject.Singleton const val TEST_SKILL_ID_0 = "test_skill_id_0" const val TEST_SKILL_ID_1 = "test_skill_id_1" @@ -421,9 +421,9 @@ class TopicController @Inject constructor( private fun createTestTopic0Story0Chapter0(): ChapterSummary { return ChapterSummary.newBuilder() - .setExplorationId(TEST_EXPLORATION_ID_0) - .setName("First Exploration") - .setSummary("This is the first Exploration summary.") + .setExplorationId(TEST_EXPLORATION_ID_30) + .setName("Prototype Exploration") + .setSummary("This is the prototype exploration to verify interaction functionality.") .setChapterPlayState(ChapterPlayState.COMPLETED) .setChapterThumbnail(createTestTopic0Story0Chapter0Thumbnail()) .build() diff --git a/domain/src/main/java/org/oppia/domain/topic/TopicListController.kt b/domain/src/main/java/org/oppia/domain/topic/TopicListController.kt index 9586891c2ba..9abc460b7a7 100644 --- a/domain/src/main/java/org/oppia/domain/topic/TopicListController.kt +++ b/domain/src/main/java/org/oppia/domain/topic/TopicListController.kt @@ -2,9 +2,6 @@ package org.oppia.domain.topic import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import java.util.concurrent.TimeUnit -import javax.inject.Inject -import javax.inject.Singleton import org.oppia.app.model.LessonThumbnail import org.oppia.app.model.LessonThumbnailGraphic import org.oppia.app.model.OngoingStoryList @@ -13,6 +10,9 @@ import org.oppia.app.model.TopicList import org.oppia.app.model.TopicSummary import org.oppia.domain.util.JsonAssetRetriever import org.oppia.util.data.AsyncResult +import java.util.concurrent.TimeUnit +import javax.inject.Inject +import javax.inject.Singleton const val TEST_TOPIC_ID_0 = "test_topic_id_0" const val TEST_TOPIC_ID_1 = "test_topic_id_1" diff --git a/domain/src/main/java/org/oppia/domain/util/InteractionObjectExtensions.kt b/domain/src/main/java/org/oppia/domain/util/InteractionObjectExtensions.kt new file mode 100644 index 00000000000..0f204212040 --- /dev/null +++ b/domain/src/main/java/org/oppia/domain/util/InteractionObjectExtensions.kt @@ -0,0 +1,70 @@ +package org.oppia.domain.util + +import org.oppia.app.model.Fraction +import org.oppia.app.model.InteractionObject +import org.oppia.app.model.InteractionObject.ObjectTypeCase.BOOL_VALUE +import org.oppia.app.model.InteractionObject.ObjectTypeCase.FRACTION +import org.oppia.app.model.InteractionObject.ObjectTypeCase.NON_NEGATIVE_INT +import org.oppia.app.model.InteractionObject.ObjectTypeCase.NORMALIZED_STRING +import org.oppia.app.model.InteractionObject.ObjectTypeCase.NUMBER_WITH_UNITS +import org.oppia.app.model.InteractionObject.ObjectTypeCase.OBJECTTYPE_NOT_SET +import org.oppia.app.model.InteractionObject.ObjectTypeCase.REAL +import org.oppia.app.model.InteractionObject.ObjectTypeCase.SET_OF_HTML_STRING +import org.oppia.app.model.InteractionObject.ObjectTypeCase.SIGNED_INT +import org.oppia.app.model.NumberUnit +import org.oppia.app.model.NumberWithUnits +import org.oppia.app.model.StringList + +/** Returns a parsable string representation of a user-submitted answer version of this [InteractionObject]. */ +fun InteractionObject.toAnswerString(): String { + return when (checkNotNull(objectTypeCase)) { + NORMALIZED_STRING -> normalizedString + SIGNED_INT -> signedInt.toString() + NON_NEGATIVE_INT -> nonNegativeInt.toString() + REAL -> real.toString() + BOOL_VALUE -> boolValue.toString() + NUMBER_WITH_UNITS -> numberWithUnits.toAnswerString() + SET_OF_HTML_STRING -> setOfHtmlString.toAnswerString() + FRACTION -> fraction.toAnswerString() + OBJECTTYPE_NOT_SET -> "" // The default InteractionObject should be an empty string. + } +} + +// https://github.com/oppia/oppia/blob/37285a/core/templates/dev/head/domain/objects/NumberWithUnitsObjectFactory.ts#L50 +private fun NumberWithUnits.toAnswerString(): String { + val prefixedUnits = unitList.filter(::isPrefixUnit) + val suffixedUnits = unitList.filterNot(::isPrefixUnit) + + val prefixString = prefixedUnits.joinToString(separator = " ") + val suffixedString = suffixedUnits.joinToString(separator = " ", transform = NumberUnit::toAnswerStringPart) + val valueString = if (numberTypeCase == NumberWithUnits.NumberTypeCase.REAL) { + real.toString() + } else { + fraction.toAnswerString() + } + + return "$prefixString$valueString $suffixedString".trim() +} + +// TODO(#152): Standardize these with a currency library. +private fun isPrefixUnit(numberUnit: NumberUnit): Boolean { + return numberUnit.unit in listOf("$", "Rs", "₹", "€", "£", "¥") +} + +// https://github.com/oppia/oppia/blob/37285a/core/templates/dev/head/domain/objects/UnitsObjectFactory.ts#L49 +private fun NumberUnit.toAnswerStringPart(): String { + return if (exponent == 1) unit else "^$unit" +} + +private fun StringList.toAnswerString(): String { + return htmlList.joinToString() +} + +// https://github.com/oppia/oppia/blob/37285a/core/templates/dev/head/domain/objects/FractionObjectFactory.ts#L47 +private fun Fraction.toAnswerString(): String { + val fractionString = if (numerator != 0) "$numerator/$denominator" else "" + val mixedString = if (wholeNumber != 0) "$wholeNumber $fractionString" else "" + val positiveFractionString = if (mixedString.isNotEmpty()) mixedString else fractionString + val negativeString = if (isNegative) "-" else "" + return if (positiveFractionString.isNotEmpty()) "$negativeString$positiveFractionString" else "0" +} diff --git a/domain/src/main/java/org/oppia/domain/util/JsonAssetRetriever.kt b/domain/src/main/java/org/oppia/domain/util/JsonAssetRetriever.kt index 44bb72ad3c2..6db29f1b04f 100644 --- a/domain/src/main/java/org/oppia/domain/util/JsonAssetRetriever.kt +++ b/domain/src/main/java/org/oppia/domain/util/JsonAssetRetriever.kt @@ -3,7 +3,6 @@ package org.oppia.domain.util import android.content.Context import org.json.JSONArray import org.json.JSONObject -import java.io.IOException import javax.inject.Inject /** Utility that retrieves JSON assets and converts them to JSON objects. */ diff --git a/domain/src/main/java/org/oppia/domain/util/StateRetriever.kt b/domain/src/main/java/org/oppia/domain/util/StateRetriever.kt old mode 100755 new mode 100644 index 3282bdf83d5..739ca3e7a59 --- a/domain/src/main/java/org/oppia/domain/util/StateRetriever.kt +++ b/domain/src/main/java/org/oppia/domain/util/StateRetriever.kt @@ -7,6 +7,8 @@ import org.oppia.app.model.AnswerGroup import org.oppia.app.model.Fraction import org.oppia.app.model.Interaction import org.oppia.app.model.InteractionObject +import org.oppia.app.model.NumberUnit +import org.oppia.app.model.NumberWithUnits import org.oppia.app.model.Outcome import org.oppia.app.model.RuleSpec import org.oppia.app.model.State @@ -119,14 +121,28 @@ class StateRetriever @Inject constructor( } return Outcome.newBuilder() .setDestStateName(outcomeJson.getString("dest")) - .setFeedback( - SubtitledHtml.newBuilder() - .setHtml(outcomeJson.getString("feedback")) - ) + .setFeedback(createFeedbackSubtitledHtml(outcomeJson)) .setLabelledAsCorrect(outcomeJson.getBoolean("labelled_as_correct")) .build() } + // TODO(#298): Remove this and only parse SubtitledHtml according the latest schema after all test explorations are + // updated. + /** + * Returns a new [SubtitledHtml] from a specified container [JSONObject] that contains an entry keyed on 'feedback'. + */ + private fun createFeedbackSubtitledHtml(containerObject: JSONObject): SubtitledHtml { + val feedbackObject = containerObject.optJSONObject("feedback") + return if (feedbackObject != null) { + SubtitledHtml.newBuilder() + .setContentId(feedbackObject.getString("content_id")) + .setHtml(feedbackObject.getString("html")) + .build() + } else { + SubtitledHtml.newBuilder().setHtml(containerObject.getString("feedback")).build() + } + } + // Creates VoiceoverMappings from JSON and adds onto State private fun createVoiceOverMappingsFromJson(recordedVoiceovers: JSONObject, stateBuilder: State.Builder) { val voiceoverMappingJson = recordedVoiceovers.getJSONObject("voiceovers_mapping") @@ -198,23 +214,14 @@ class StateRetriever @Inject constructor( "TextInput" -> InteractionObject.newBuilder() .setNormalizedString(inputJson.getString(keyName)) .build() + "NumberWithUnits" -> InteractionObject.newBuilder() + .setNumberWithUnits(parseNumberWithUnitsObject(inputJson.getJSONObject(keyName))) + .build() "NumericInput" -> InteractionObject.newBuilder() .setReal(inputJson.getDouble(keyName)) .build() "FractionInput" -> InteractionObject.newBuilder() - .setFraction( - Fraction.newBuilder() - .setDenominator(inputJson.getJSONObject(keyName).getInt("denominator")) - .setNumerator(inputJson.getJSONObject(keyName).getInt("numerator")) - .setIsNegative(inputJson.getJSONObject(keyName).getBoolean("isNegative")) - .setWholeNumber(inputJson.getJSONObject(keyName).getInt("wholeNumber")) - ).build() - "ItemSelectionInput" -> InteractionObject.newBuilder() - .setSetOfHtmlString( - StringList.newBuilder().addAllHtml( - jsonAssetRetriever.getStringsFromJSONArray(inputJson.getJSONArray(keyName)) - ) - ) + .setFraction(parseFraction(inputJson.getJSONObject(keyName))) .build() else -> throw IllegalStateException("Encountered unexpected interaction ID: $interactionId") } @@ -228,6 +235,31 @@ class StateRetriever @Inject constructor( return stringListBuilder.build() } + private fun parseNumberWithUnitsObject(numberWithUnitsAnswer: JSONObject): NumberWithUnits { + val numberWithUnitsBuilder = NumberWithUnits.newBuilder() + when (numberWithUnitsAnswer.getString("type")) { + "real" -> numberWithUnitsBuilder.real = numberWithUnitsAnswer.getDouble("real") + "fraction" -> numberWithUnitsBuilder.fraction = parseFraction(numberWithUnitsAnswer.getJSONObject("fraction")) + } + val unitsArray = numberWithUnitsAnswer.getJSONArray("units") + for (i in 0 until unitsArray.length()) { + val unit = unitsArray.getJSONObject(i) + numberWithUnitsBuilder.addUnit(NumberUnit.newBuilder() + .setUnit(unit.getString("unit")) + .setExponent(unit.getInt("exponent"))) + } + return numberWithUnitsBuilder.build() + } + + private fun parseFraction(fractionAnswer: JSONObject): Fraction { + return Fraction.newBuilder() + .setWholeNumber(fractionAnswer.getInt("wholeNumber")) + .setDenominator(fractionAnswer.getInt("denominator")) + .setNumerator(fractionAnswer.getInt("numerator")) + .setIsNegative(fractionAnswer.getBoolean("isNegative")) + .build() + } + // Creates a customization arg mapping from JSON private fun createCustomizationArgsMapFromJson( customizationArgsJson: JSONObject? @@ -251,14 +283,10 @@ class StateRetriever @Inject constructor( private fun createCustomizationArgValueFromJson(customizationArgValue: Any): InteractionObject { val interactionObjectBuilder = InteractionObject.newBuilder() when (customizationArgValue) { - is String -> return interactionObjectBuilder - .setNormalizedString(customizationArgValue).build() - is Int -> return interactionObjectBuilder - .setSignedInt(customizationArgValue).build() - is Double -> return interactionObjectBuilder - .setReal(customizationArgValue).build() - is Boolean -> return interactionObjectBuilder - .setBoolValue(customizationArgValue).build() + is String -> return interactionObjectBuilder.setNormalizedString(customizationArgValue).build() + is Int -> return interactionObjectBuilder.setSignedInt(customizationArgValue).build() + is Double -> return interactionObjectBuilder.setReal(customizationArgValue).build() + is Boolean -> return interactionObjectBuilder.setBoolValue(customizationArgValue).build() else -> { val customizationArgValueTemp: ArrayList<*> = Gson().fromJson(customizationArgValue.toString(), ArrayList::class.java) diff --git a/domain/src/test/java/org/oppia/domain/audio/AudioPlayerControllerTest.kt b/domain/src/test/java/org/oppia/domain/audio/AudioPlayerControllerTest.kt index 5e35ab6058e..b7cf589819c 100644 --- a/domain/src/test/java/org/oppia/domain/audio/AudioPlayerControllerTest.kt +++ b/domain/src/test/java/org/oppia/domain/audio/AudioPlayerControllerTest.kt @@ -6,6 +6,7 @@ import android.net.Uri import androidx.lifecycle.Observer import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component import dagger.Module @@ -18,10 +19,15 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor import org.mockito.Mock +import org.mockito.Mockito.atLeastOnce +import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule -import org.mockito.Mockito.verify +import org.oppia.domain.audio.AudioPlayerController.PlayStatus +import org.oppia.util.data.AsyncResult import org.oppia.util.logging.EnableConsoleLog import org.oppia.util.logging.EnableFileLog import org.oppia.util.logging.GlobalLogLevel @@ -30,19 +36,12 @@ import org.oppia.util.threading.BackgroundDispatcher import org.oppia.util.threading.BlockingDispatcher import org.robolectric.Shadows import org.robolectric.annotation.Config -import javax.inject.Inject -import javax.inject.Singleton -import com.google.common.truth.Truth.assertThat -import org.mockito.ArgumentCaptor -import org.mockito.Captor -import org.mockito.Mockito.atLeastOnce -import org.oppia.util.data.AsyncResult import org.robolectric.shadows.ShadowMediaPlayer import org.robolectric.shadows.util.DataSource +import javax.inject.Inject import javax.inject.Qualifier +import javax.inject.Singleton import kotlin.coroutines.EmptyCoroutineContext -import org.oppia.domain.audio.AudioPlayerController.PlayStatus -import java.lang.IllegalStateException import kotlin.reflect.KClass import kotlin.reflect.full.cast import kotlin.test.fail diff --git a/domain/src/test/java/org/oppia/domain/audio/CellularDialogControllerTest.kt b/domain/src/test/java/org/oppia/domain/audio/CellularDialogControllerTest.kt index 08d11638e9f..2cde27862ea 100644 --- a/domain/src/test/java/org/oppia/domain/audio/CellularDialogControllerTest.kt +++ b/domain/src/test/java/org/oppia/domain/audio/CellularDialogControllerTest.kt @@ -1,6 +1,5 @@ package org.oppia.domain.audio -import org.oppia.domain.UserAppHistoryController import android.app.Application import android.content.Context import androidx.lifecycle.Observer @@ -28,6 +27,7 @@ import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule import org.oppia.app.model.CellularDataPreference +import org.oppia.domain.UserAppHistoryController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.EnableConsoleLog import org.oppia.util.logging.EnableFileLog diff --git a/domain/src/test/java/org/oppia/domain/classify/AnswerClassificationControllerTest.kt b/domain/src/test/java/org/oppia/domain/classify/AnswerClassificationControllerTest.kt index 81796e86877..adef3d98873 100644 --- a/domain/src/test/java/org/oppia/domain/classify/AnswerClassificationControllerTest.kt +++ b/domain/src/test/java/org/oppia/domain/classify/AnswerClassificationControllerTest.kt @@ -76,10 +76,10 @@ class AnswerClassificationControllerTest { private val TEST_MULTIPLE_CHOICE_OPTION_1 = InteractionObject.newBuilder().setNonNegativeInt(1).build() private val TEST_NUMBER_WITH_UNITS_0 = InteractionObject.newBuilder() - .setNumberWithUnits(NumberWithUnits.newBuilder().setReal(1.0f).addUnit(NumberUnit.newBuilder().setUnit("cm"))) + .setNumberWithUnits(NumberWithUnits.newBuilder().setReal(1.0).addUnit(NumberUnit.newBuilder().setUnit("cm"))) .build() private val TEST_NUMBER_WITH_UNITS_1 = InteractionObject.newBuilder() - .setNumberWithUnits(NumberWithUnits.newBuilder().setReal(1.0f).addUnit(NumberUnit.newBuilder().setUnit("m"))) + .setNumberWithUnits(NumberWithUnits.newBuilder().setReal(1.0).addUnit(NumberUnit.newBuilder().setUnit("m"))) .build() private val TEST_NUMBER_0 = InteractionObject.newBuilder().setReal(1.0).build() diff --git a/domain/src/test/java/org/oppia/domain/profile/ProfileManagementControllerTest.kt b/domain/src/test/java/org/oppia/domain/profile/ProfileManagementControllerTest.kt index 05fb4c77b86..25c1fce554b 100644 --- a/domain/src/test/java/org/oppia/domain/profile/ProfileManagementControllerTest.kt +++ b/domain/src/test/java/org/oppia/domain/profile/ProfileManagementControllerTest.kt @@ -5,7 +5,6 @@ import android.content.Context import androidx.lifecycle.Observer import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component import dagger.Module @@ -27,8 +26,6 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock -import org.mockito.Mockito.atLeastOnce -import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule import org.oppia.util.data.AsyncResult diff --git a/model/src/main/proto/interaction_object.proto b/model/src/main/proto/interaction_object.proto index 662337f37b6..0a87bf0e135 100644 --- a/model/src/main/proto/interaction_object.proto +++ b/model/src/main/proto/interaction_object.proto @@ -29,7 +29,7 @@ message StringList { // Structure for a number with units object. message NumberWithUnits { oneof number_type { - float real = 1; + double real = 1; Fraction fraction = 2; } repeated NumberUnit unit = 3; diff --git a/utility/src/main/java/org/oppia/util/data/DataProviders.kt b/utility/src/main/java/org/oppia/util/data/DataProviders.kt index 82cc4f13aed..cd71e726d6d 100644 --- a/utility/src/main/java/org/oppia/util/data/DataProviders.kt +++ b/utility/src/main/java/org/oppia/util/data/DataProviders.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.oppia.util.threading.BackgroundDispatcher diff --git a/utility/src/main/java/org/oppia/util/logging/Logger.kt b/utility/src/main/java/org/oppia/util/logging/Logger.kt index 65d29f27cf6..7738501e425 100644 --- a/utility/src/main/java/org/oppia/util/logging/Logger.kt +++ b/utility/src/main/java/org/oppia/util/logging/Logger.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.oppia.util.threading.BlockingDispatcher import java.io.File -import java.util.Calendar +import java.util.* import javax.inject.Inject import javax.inject.Singleton diff --git a/utility/src/main/java/org/oppia/util/parser/ExplorationHtmlParserEntityType.kt b/utility/src/main/java/org/oppia/util/parser/ExplorationHtmlParserEntityType.kt old mode 100755 new mode 100644 diff --git a/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt b/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt index 2f062eb088b..602b26c560e 100644 --- a/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt +++ b/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt @@ -2,11 +2,8 @@ package org.oppia.util.parser import android.content.Context import android.graphics.Bitmap -import android.graphics.drawable.Drawable -import android.widget.ImageView import com.bumptech.glide.Glide import com.bumptech.glide.request.target.CustomTarget -import com.bumptech.glide.request.target.SimpleTarget import javax.inject.Inject /** An [ImageLoader] that uses Glide. */ diff --git a/utility/src/main/java/org/oppia/util/parser/GlideImageLoaderModule.kt b/utility/src/main/java/org/oppia/util/parser/GlideImageLoaderModule.kt index 289fe78c163..7a3289fb77f 100644 --- a/utility/src/main/java/org/oppia/util/parser/GlideImageLoaderModule.kt +++ b/utility/src/main/java/org/oppia/util/parser/GlideImageLoaderModule.kt @@ -3,8 +3,10 @@ package org.oppia.util.parser import dagger.Binds import dagger.Module +/** Provides image loading dependencies. */ @Module abstract class GlideImageLoaderModule { + @Binds abstract fun provideGlideImageLoader(impl: GlideImageLoader): ImageLoader } diff --git a/utility/src/main/java/org/oppia/util/parser/HtmlParser.kt b/utility/src/main/java/org/oppia/util/parser/HtmlParser.kt index ea10cd21de3..6ee8e0dad30 100755 --- a/utility/src/main/java/org/oppia/util/parser/HtmlParser.kt +++ b/utility/src/main/java/org/oppia/util/parser/HtmlParser.kt @@ -1,6 +1,5 @@ package org.oppia.util.parser -import android.content.Context import android.text.Html import android.text.Spannable import android.widget.TextView diff --git a/utility/src/main/java/org/oppia/util/parser/HtmlParserEntityTypeModule.kt b/utility/src/main/java/org/oppia/util/parser/HtmlParserEntityTypeModule.kt old mode 100755 new mode 100644 diff --git a/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt b/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt index 7334ac0503e..1035893ba9e 100755 --- a/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt +++ b/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt @@ -1,11 +1,6 @@ package org.oppia.util.parser -import android.content.Context import android.graphics.Bitmap -import android.graphics.drawable.Drawable -import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.SimpleTarget -import androidx.annotation.DrawableRes import com.bumptech.glide.request.target.CustomTarget /** Loads an image from the provided URL into the specified target, optionally caching it. */ diff --git a/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt b/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt index ee85f115382..e274b8b0eee 100755 --- a/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt +++ b/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt @@ -24,9 +24,8 @@ class UrlImageParser private constructor( private val htmlContentTextView: TextView, private val entityType: String, private val entityId: String, - private val imageLoader:ImageLoader + private val imageLoader: ImageLoader ) : Html.ImageGetter { - /** * This method is called when the HTML parser encounters an tag. * @param urlString : urlString argument is the string from the "src" attribute. @@ -45,15 +44,16 @@ class UrlImageParser private constructor( private inner class BitmapTarget(private val urlDrawable: UrlDrawable) : CustomTarget