diff --git a/app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt b/app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt index a5284d84d4a..79f403ec3dc 100644 --- a/app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt +++ b/app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt @@ -7,7 +7,6 @@ import dagger.Component import org.oppia.android.app.activity.ActivityComponent import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -24,6 +23,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.ApplicationStartupListener import org.oppia.android.domain.oppialogger.LogStorageModule @@ -76,10 +77,11 @@ import javax.inject.Singleton ExpirationMetaDataRetrieverModule::class, RatioInputModule::class, UncaughtExceptionLoggerModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, - HintsAndSolutionConfigModule::class, FirebaseLogUploaderModule::class, - NetworkModule::class, PracticeTabModule::class, PlatformParameterModule::class, - ExplorationStorageModule::class, DeveloperOptionsStarterModule::class, - DeveloperOptionsModule::class, NetworkConnectionUtilDebugModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, + FirebaseLogUploaderModule::class, NetworkModule::class, PracticeTabModule::class, + PlatformParameterModule::class, ExplorationStorageModule::class, + DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, + NetworkConnectionUtilDebugModule::class, // TODO(#59): Remove this module once we completely migrate to Bazel from Gradle as we can then // directly exclude debug files from the build and thus won't be requiring this module. NetworkConnectionDebugUtilModule::class diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragment.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragment.kt index 2bac511617d..6ce3529b875 100644 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragment.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragment.kt @@ -7,12 +7,14 @@ import android.view.View import android.view.ViewGroup import org.oppia.android.R import org.oppia.android.app.fragment.InjectableDialogFragment +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.State +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.putProto import javax.inject.Inject private const val CURRENT_EXPANDED_LIST_INDEX_SAVED_KEY = "HintsAndSolutionDialogFragment.current_expanded_list_index" -private const val STATE_SAVED_KEY = "HintsAndSolutionDialogFragment.state" private const val HINT_INDEX_SAVED_KEY = "HintsAndSolutionDialogFragment.hint_index" private const val IS_HINT_REVEALED_SAVED_KEY = "HintsAndSolutionDialogFragment.is_hint_revealed" private const val SOLUTION_INDEX_SAVED_KEY = "HintsAndSolutionDialogFragment.solution_index" @@ -28,8 +30,6 @@ class HintsAndSolutionDialogFragment : @Inject lateinit var hintsAndSolutionDialogFragmentPresenter: HintsAndSolutionDialogFragmentPresenter - private lateinit var state: State - private var currentExpandedHintListIndex: Int? = null private var index: Int? = null @@ -40,30 +40,29 @@ class HintsAndSolutionDialogFragment : companion object { internal const val ID_ARGUMENT_KEY = "HintsAndSolutionDialogFragment.id" - internal const val NEW_AVAILABLE_HINT_INDEX_ARGUMENT_KEY = - "HintsAndSolutionDialogFragment.new_available_hint_index" - internal const val ALL_HINTS_EXHAUSTED_ARGUMENT_KEY = - "HintsAndSolutionDialogFragment.all_hints_exhausted" + internal const val STATE_KEY = "HintsAndSolutionDialogFragment.state" + internal const val HELP_INDEX_KEY = "HintsAndSolutionDialogFragment.help_index" /** * Creates a new instance of a DialogFragment to display hints and solution + * * @param id Used in ExplorationController/QuestionAssessmentProgressController to get current state data. - * @param newAvailableHintIndex Index of new available hint. - * @param allHintsExhausted Boolean set to true when all hints are exhausted. + * @param state the [State] being viewed by the learner + * @param helpIndex the [HelpIndex] corresponding to the current hints/solution configuration * @return [HintsAndSolutionDialogFragment]: DialogFragment */ fun newInstance( id: String, - newAvailableHintIndex: Int, - allHintsExhausted: Boolean + state: State, + helpIndex: HelpIndex ): HintsAndSolutionDialogFragment { - val hintsAndSolutionFrag = HintsAndSolutionDialogFragment() - val args = Bundle() - args.putString(ID_ARGUMENT_KEY, id) - args.putInt(NEW_AVAILABLE_HINT_INDEX_ARGUMENT_KEY, newAvailableHintIndex) - args.putBoolean(ALL_HINTS_EXHAUSTED_ARGUMENT_KEY, allHintsExhausted) - hintsAndSolutionFrag.arguments = args - return hintsAndSolutionFrag + return HintsAndSolutionDialogFragment().apply { + arguments = Bundle().apply { + putString(ID_ARGUMENT_KEY, id) + putProto(STATE_KEY, state) + putProto(HELP_INDEX_KEY, helpIndex) + } + } } } @@ -88,7 +87,6 @@ class HintsAndSolutionDialogFragment : if (currentExpandedHintListIndex == -1) { currentExpandedHintListIndex = null } - state = State.parseFrom(savedInstanceState.getByteArray(STATE_SAVED_KEY)!!) index = savedInstanceState.getInt(HINT_INDEX_SAVED_KEY, -1) if (index == -1) index = null isHintRevealed = savedInstanceState.getBoolean(IS_HINT_REVEALED_SAVED_KEY, false) @@ -104,23 +102,17 @@ class HintsAndSolutionDialogFragment : checkNotNull( args.getString(ID_ARGUMENT_KEY) ) { "Expected id to be passed to HintsAndSolutionDialogFragment" } - val newAvailableHintIndex = - checkNotNull( - args.getInt(NEW_AVAILABLE_HINT_INDEX_ARGUMENT_KEY) - ) { "Expected hint index to be passed to HintsAndSolutionDialogFragment" } - val allHintsExhausted = - checkNotNull( - args.getBoolean(ALL_HINTS_EXHAUSTED_ARGUMENT_KEY) - ) { "Expected if hints exhausted to be passed to HintsAndSolutionDialogFragment" } + + val state = args.getProto(STATE_KEY, State.getDefaultInstance()) + val helpIndex = args.getProto(HELP_INDEX_KEY, HelpIndex.getDefaultInstance()) return hintsAndSolutionDialogFragmentPresenter.handleCreateView( inflater, container, state, + helpIndex, id, currentExpandedHintListIndex, - newAvailableHintIndex, - allHintsExhausted, this as ExpandedHintListIndexListener, index, isHintRevealed, @@ -151,7 +143,6 @@ class HintsAndSolutionDialogFragment : if (isSolutionRevealed != null) { outState.putBoolean(IS_SOLUTION_REVEALED_SAVED_KEY, isSolutionRevealed!!) } - outState.putByteArray(STATE_SAVED_KEY, state.toByteArray()) } override fun onExpandListIconClicked(index: Int?) { @@ -177,8 +168,4 @@ class HintsAndSolutionDialogFragment : isSolutionRevealed ) } - - fun loadState(state: State) { - this.state = state - } } diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt index 2a3930441b8..e1ab2270bb4 100644 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt @@ -6,6 +6,11 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import org.oppia.android.R import org.oppia.android.app.fragment.FragmentScope +import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.EVERYTHING_REVEALED +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.LATEST_REVEALED_HINT_INDEX +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.SHOW_SOLUTION import org.oppia.android.app.model.State import org.oppia.android.app.recyclerview.BindableAdapter import org.oppia.android.app.viewmodel.ViewModelProvider @@ -16,6 +21,7 @@ import org.oppia.android.databinding.SolutionSummaryBinding import org.oppia.android.util.gcsresource.DefaultResourceBucketName import org.oppia.android.util.parser.html.ExplorationHtmlParserEntityType import org.oppia.android.util.parser.html.HtmlParser +import java.lang.IllegalStateException import java.util.Locale import javax.inject.Inject @@ -39,6 +45,7 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( private lateinit var expandedHintListIndexListener: ExpandedHintListIndexListener private lateinit var binding: HintsAndSolutionFragmentBinding private lateinit var state: State + private lateinit var helpIndex: HelpIndex private lateinit var itemList: List private lateinit var bindingAdapter: BindableAdapter @@ -54,17 +61,15 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( inflater: LayoutInflater, container: ViewGroup?, state: State, + helpIndex: HelpIndex, id: String?, currentExpandedHintListIndex: Int?, - newAvailableHintIndex: Int, - allHintsExhausted: Boolean, expandedHintListIndexListener: ExpandedHintListIndexListener, index: Int?, isHintRevealed: Boolean?, solutionIndex: Int?, isSolutionRevealed: Boolean? ): View? { - binding = HintsAndSolutionFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) this.currentExpandedHintListIndex = currentExpandedHintListIndex @@ -86,13 +91,15 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( } this.state = state - // The newAvailableHintIndex received here is coming from state player but in this implementation - // hints/solutions are shown on every even index and on every odd index we show a divider. - // Therefore multiplying the original index by 2. + this.helpIndex = helpIndex + // The newAvailableHintIndex received here is coming from state player but in this + // implementation hints/solutions are shown on every even index and on every odd index we show a + // divider. The relative index therefore needs to be doubled to account for the divider. + val newAvailableHintIndex = computeNewAvailableHintIndex(helpIndex) viewModel.newAvailableHintIndex.set( newAvailableHintIndex * RECYCLERVIEW_INDEX_CORRECTION_MULTIPLIER ) - viewModel.allHintsExhausted.set(allHintsExhausted) + viewModel.allHintsExhausted.set(computeWhetherAllHintsAreExhausted(helpIndex)) viewModel.explorationId.set(id) loadHintsAndSolution(state) @@ -100,11 +107,36 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( return binding.root } + private fun computeNewAvailableHintIndex(helpIndex: HelpIndex): Int { + return when (helpIndex.indexTypeCase) { + NEXT_AVAILABLE_HINT_INDEX -> helpIndex.nextAvailableHintIndex + LATEST_REVEALED_HINT_INDEX -> helpIndex.latestRevealedHintIndex + SHOW_SOLUTION, EVERYTHING_REVEALED -> { + // 1 is subtracted from the hint count because hints are indexed from 0. + state.interaction.hintCount - 1 + } + else -> + throw IllegalStateException( + "Encountered invalid type for showing hints: ${helpIndex.indexTypeCase}" + ) + } + } + + private fun computeWhetherAllHintsAreExhausted(helpIndex: HelpIndex): Boolean { + return when (helpIndex.indexTypeCase) { + NEXT_AVAILABLE_HINT_INDEX, LATEST_REVEALED_HINT_INDEX -> false + SHOW_SOLUTION, EVERYTHING_REVEALED -> true + else -> + throw IllegalStateException( + "Encountered invalid type for showing hints: ${helpIndex.indexTypeCase}" + ) + } + } + private fun loadHintsAndSolution(state: State) { // Check if hints are available for this state. - if (state.interaction.hintList.size != 0) { - viewModel.setHintsList(state.interaction.hintList) - viewModel.setSolution(state.interaction.solution) + if (state.interaction.hintList.isNotEmpty()) { + viewModel.initialize(helpIndex, state.interaction.hintList, state.interaction.solution) itemList = viewModel.processHintList() @@ -203,7 +235,6 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( hintsViewModel.isHintRevealed.set(true) expandedHintListIndexListener.onRevealHintClicked(position, /* isHintRevealed= */ true) (fragment.requireActivity() as? RevealHintListener)?.revealHint( - saveUserChoice = true, hintIndex = position / RECYCLERVIEW_INDEX_CORRECTION_MULTIPLIER ) val previousIndex: Int? = currentExpandedHintListIndex diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt index d7fc46cabf4..8e964bc094e 100644 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt @@ -3,8 +3,11 @@ package org.oppia.android.app.hintsandsolution import androidx.databinding.ObservableField import androidx.lifecycle.ViewModel import org.oppia.android.app.fragment.FragmentScope +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.Hint import org.oppia.android.app.model.Solution +import org.oppia.android.domain.hintsandsolution.isHintRevealed +import org.oppia.android.domain.hintsandsolution.isSolutionRevealed import javax.inject.Inject /** @@ -29,13 +32,13 @@ class HintsViewModel @Inject constructor() : HintsAndSolutionItemViewModel() { private lateinit var hintList: List private lateinit var solution: Solution + private lateinit var helpIndex: HelpIndex val itemList: MutableList = ArrayList() - fun setHintsList(hintList: List) { + /** Initializes the view model to display hints and a solution. */ + fun initialize(helpIndex: HelpIndex, hintList: List, solution: Solution) { + this.helpIndex = helpIndex this.hintList = hintList - } - - fun setSolution(solution: Solution) { this.solution = solution } @@ -43,7 +46,7 @@ class HintsViewModel @Inject constructor() : HintsAndSolutionItemViewModel() { itemList.clear() for (index in hintList.indices) { if (itemList.isEmpty()) { - addHintToList(hintList[index]) + addHintToList(index, hintList[index]) } else if (itemList.size > 1) { val isLastHintRevealed = (itemList[itemList.size - RECYCLERVIEW_INDEX_CORRECTION_MULTIPLIER] as HintsViewModel) @@ -53,7 +56,7 @@ class HintsViewModel @Inject constructor() : HintsAndSolutionItemViewModel() { if (isLastHintRevealed && index <= availableHintIndex / RECYCLERVIEW_INDEX_CORRECTION_MULTIPLIER ) { - addHintToList(hintList[index]) + addHintToList(index, hintList[index]) } else { break } @@ -76,11 +79,11 @@ class HintsViewModel @Inject constructor() : HintsAndSolutionItemViewModel() { return itemList } - private fun addHintToList(hint: Hint) { + private fun addHintToList(hintIndex: Int, hint: Hint) { val hintsViewModel = HintsViewModel() hintsViewModel.title.set(hint.hintContent.contentId) hintsViewModel.hintsAndSolutionSummary.set(hint.hintContent.html) - hintsViewModel.isHintRevealed.set(hint.hintIsRevealed) + hintsViewModel.isHintRevealed.set(helpIndex.isHintRevealed(hintIndex, hintList)) itemList.add(hintsViewModel) addDividerItem() } @@ -94,7 +97,7 @@ class HintsViewModel @Inject constructor() : HintsAndSolutionItemViewModel() { solutionViewModel.wholeNumber.set(solution.correctAnswer.wholeNumber) solutionViewModel.isNegative.set(solution.correctAnswer.isNegative) solutionViewModel.solutionSummary.set(solution.explanation.html) - solutionViewModel.isSolutionRevealed.set(solution.solutionIsRevealed) + solutionViewModel.isSolutionRevealed.set(helpIndex.isSolutionRevealed()) itemList.add(solutionViewModel) addDividerItem() } diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/RevealHintListener.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/RevealHintListener.kt index 72b263c6842..3614504dd22 100755 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/RevealHintListener.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/RevealHintListener.kt @@ -1,10 +1,10 @@ package org.oppia.android.app.hintsandsolution -/** Interface to check the preference regarding alert for [HintsAndSolutionDialogFragment]. */ +/** Callback listener for when the user wishes to reveal a hint. */ interface RevealHintListener { /** - * If saveUserChoice is true, show solution and save preference do not show dialog again. - * If saveUserChoice is false, show solution and do not save preference and show this dialog next time too. + * Called when the user indicates they want to reveal the hint corresponding to the specified + * index. */ - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) + fun revealHint(hintIndex: Int) } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt index 36e49d22588..98b3dd8acd4 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt @@ -11,6 +11,7 @@ import org.oppia.android.app.hintsandsolution.HintsAndSolutionDialogFragment import org.oppia.android.app.hintsandsolution.HintsAndSolutionListener import org.oppia.android.app.hintsandsolution.RevealHintListener import org.oppia.android.app.hintsandsolution.RevealSolutionInterface +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.app.model.State import org.oppia.android.app.player.audio.AudioButtonListener @@ -143,8 +144,8 @@ class ExplorationActivity : explorationActivityPresenter.onKeyboardAction(actionCode) } - override fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - explorationActivityPresenter.revealHint(saveUserChoice, hintIndex) + override fun revealHint(hintIndex: Int) { + explorationActivityPresenter.revealHint(hintIndex) } override fun revealSolution() = explorationActivityPresenter.revealSolution() @@ -157,16 +158,14 @@ class ExplorationActivity : override fun routeToHintsAndSolution( explorationId: String, - newAvailableHintIndex: Int, - allHintsExhausted: Boolean + helpIndex: HelpIndex ) { if (getHintsAndSolution() == null) { val hintsAndSolutionDialogFragment = HintsAndSolutionDialogFragment.newInstance( explorationId, - newAvailableHintIndex, - allHintsExhausted + state, + helpIndex ) - hintsAndSolutionDialogFragment.loadState(state) hintsAndSolutionDialogFragment.showNow(supportFragmentManager, TAG_HINTS_AND_SOLUTION_DIALOG) } } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt index d3f6cb2698c..aa1edfe9e04 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt @@ -344,12 +344,12 @@ class ExplorationActivityPresenter @Inject constructor( } } - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { + fun revealHint(hintIndex: Int) { val explorationFragment = activity.supportFragmentManager.findFragmentByTag( TAG_EXPLORATION_FRAGMENT ) as ExplorationFragment - explorationFragment.revealHint(saveUserChoice, hintIndex) + explorationFragment.revealHint(hintIndex) } fun revealSolution() { diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt index 6d2fd65be2a..0ef77ff9b72 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt @@ -100,8 +100,8 @@ class ExplorationFragment : InjectableFragment() { fun scrollToTop() = explorationFragmentPresenter.scrollToTop() - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - explorationFragmentPresenter.revealHint(saveUserChoice, hintIndex) + fun revealHint(hintIndex: Int) { + explorationFragmentPresenter.revealHint(hintIndex) } fun revealSolution() { diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt index 08d031174a2..877ca078208 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt @@ -54,8 +54,8 @@ class ExplorationFragmentPresenter @Inject constructor( getStateFragment()?.handleKeyboardAction() } - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - getStateFragment()?.revealHint(saveUserChoice, hintIndex) + fun revealHint(hintIndex: Int) { + getStateFragment()?.revealHint(hintIndex) } fun revealSolution() { diff --git a/app/src/main/java/org/oppia/android/app/player/state/StateFragment.kt b/app/src/main/java/org/oppia/android/app/player/state/StateFragment.kt index 6ebd407be15..1d3707a1f21 100755 --- a/app/src/main/java/org/oppia/android/app/player/state/StateFragment.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/StateFragment.kt @@ -103,8 +103,8 @@ class StateFragment : override fun onResponsesHeaderClicked() = stateFragmentPresenter.onResponsesHeaderClicked() - override fun onHintAvailable(helpIndex: HelpIndex) = - stateFragmentPresenter.onHintAvailable(helpIndex) + override fun onHintAvailable(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) = + stateFragmentPresenter.onHintAvailable(helpIndex, isCurrentStatePendingState) fun handlePlayAudio() = stateFragmentPresenter.handleAudioClick() @@ -122,8 +122,8 @@ class StateFragment : fun scrollToTop() = stateFragmentPresenter.scrollToTop() - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - stateFragmentPresenter.revealHint(saveUserChoice, hintIndex) + fun revealHint(hintIndex: Int) { + stateFragmentPresenter.revealHint(hintIndex) } fun revealSolution() = stateFragmentPresenter.revealSolution() diff --git a/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt index 833180b49d3..09842da300e 100755 --- a/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt @@ -20,9 +20,7 @@ import org.oppia.android.app.model.AnswerOutcome import org.oppia.android.app.model.CheckpointState import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.HelpIndex -import org.oppia.android.app.model.Hint import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.State import org.oppia.android.app.model.UserAnswer import org.oppia.android.app.player.audio.AudioButtonListener @@ -83,6 +81,7 @@ class StateFragmentPresenter @Inject constructor( private lateinit var currentStateName: String private lateinit var binding: StateFragmentBinding private lateinit var recyclerViewAdapter: RecyclerView.Adapter<*> + private lateinit var helpIndex: HelpIndex private val viewModel: StateViewModel by lazy { getStateViewModel() @@ -149,8 +148,7 @@ class StateFragmentPresenter @Inject constructor( binding.hintsAndSolutionFragmentContainer.setOnClickListener { routeToHintsAndSolutionListener.routeToHintsAndSolution( this.explorationId, - viewModel.newAvailableHintIndex, - viewModel.allHintsExhausted + helpIndex ) } @@ -201,28 +199,6 @@ class StateFragmentPresenter @Inject constructor( recyclerViewAssembler.adapter.notifyDataSetChanged() } - fun onHintAvailable(helpIndex: HelpIndex) { - when (helpIndex.indexTypeCase) { - HelpIndex.IndexTypeCase.HINT_INDEX, HelpIndex.IndexTypeCase.SHOW_SOLUTION -> { - if (helpIndex.indexTypeCase == HelpIndex.IndexTypeCase.HINT_INDEX) { - viewModel.newAvailableHintIndex = helpIndex.hintIndex - } - viewModel.allHintsExhausted = - helpIndex.indexTypeCase == HelpIndex.IndexTypeCase.SHOW_SOLUTION - viewModel.setHintOpenedAndUnRevealedVisibility(true) - viewModel.setHintBulbVisibility(true) - } - HelpIndex.IndexTypeCase.EVERYTHING_REVEALED -> { - viewModel.setHintOpenedAndUnRevealedVisibility(false) - viewModel.setHintBulbVisibility(true) - } - else -> { - viewModel.setHintOpenedAndUnRevealedVisibility(false) - viewModel.setHintBulbVisibility(false) - } - } - } - fun handleAudioClick() = recyclerViewAssembler.toggleAudioPlaybackState() fun handleKeyboardAction() { @@ -232,6 +208,11 @@ class StateFragmentPresenter @Inject constructor( } } + fun onHintAvailable(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) { + this.helpIndex = helpIndex + showHintsAndSolutions(helpIndex, isCurrentStatePendingState) + } + private fun createRecyclerViewAssembler( builder: StatePlayerRecyclerViewAssembler.Builder, congratulationsTextView: TextView, @@ -267,18 +248,12 @@ class StateFragmentPresenter @Inject constructor( .build() } - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - subscribeToHint( - explorationProgressController.submitHintIsRevealed( - currentState, - saveUserChoice, - hintIndex - ) - ) + fun revealHint(hintIndex: Int) { + subscribeToHintSolution(explorationProgressController.submitHintIsRevealed(hintIndex)) } fun revealSolution() { - subscribeToSolution(explorationProgressController.submitSolutionIsRevealed(currentState)) + subscribeToHintSolution(explorationProgressController.submitSolutionIsRevealed()) } private fun getStateViewModel(): StateViewModel { @@ -336,6 +311,7 @@ class StateFragmentPresenter @Inject constructor( currentState = ephemeralState.state currentStateName = ephemeralState.state.name + showOrHideAudioByState(ephemeralState.state) val dataPair = recyclerViewAssembler.compute( @@ -357,38 +333,17 @@ class StateFragmentPresenter @Inject constructor( } } - /** - * This function listens to the result of RevealHint. - * Whenever a hint is revealed using ExplorationProgressController.submitHintIsRevealed function, - * this function will wait for the response from that function and based on which we can move to - * next state. - */ - private fun subscribeToHint(hintResultLiveData: LiveData>) { - val hintLiveData = getHintIsRevealed(hintResultLiveData) - hintLiveData.observe( + /** Subscribes to the result of requesting to show a hint or solution. */ + private fun subscribeToHintSolution(resultLiveData: LiveData>) { + resultLiveData.observe( fragment, - Observer { result -> - // If the hint was revealed remove dot and radar. - if (result.hintIsRevealed) { - viewModel.setHintOpenedAndUnRevealedVisibility(false) - } - } - ) - } - - /** - * This function listens to the result of RevealSolution. - * Whenever a hint is revealed using ExplorationProgressController.submitHintIsRevealed function, - * this function will wait for the response from that function and based on which we can move to - * next state. - */ - private fun subscribeToSolution(solutionResultLiveData: LiveData>) { - val solutionLiveData = getSolutionIsRevealed(solutionResultLiveData) - solutionLiveData.observe( - fragment, - Observer { result -> - // If the hint was revealed remove dot and radar. - if (result.solutionIsRevealed) { + { result -> + if (result.isFailure()) { + oppiaLogger.e( + "StateFragment", "Failed to retrieve hint/solution", result.getErrorOrNull()!! + ) + } else { + // If the hint/solution, was revealed remove dot and radar. viewModel.setHintOpenedAndUnRevealedVisibility(false) } } @@ -408,15 +363,12 @@ class StateFragmentPresenter @Inject constructor( answerOutcomeLiveData.observe( fragment, Observer { result -> - // If the answer was submitted on behalf of the Continue interaction, automatically continue to the next state. + // If the answer was submitted on behalf of the Continue interaction, automatically continue + // to the next state. if (result.state.interaction.id == "Continue") { - recyclerViewAssembler.stopHintsFromShowing() - viewModel.setHintBulbVisibility(false) moveToNextState() } else { if (result.labelledAsCorrectAnswer) { - recyclerViewAssembler.stopHintsFromShowing() - viewModel.setHintBulbVisibility(false) recyclerViewAssembler.showCelebrationOnCorrectAnswer() } else { viewModel.setCanSubmitAnswer(canSubmitAnswer = false) @@ -427,16 +379,6 @@ class StateFragmentPresenter @Inject constructor( ) } - /** Helper for [subscribeToSolution]. */ - private fun getSolutionIsRevealed(hint: LiveData>): LiveData { - return Transformations.map(hint, ::processSolution) - } - - /** Helper for [subscribeToHint]. */ - private fun getHintIsRevealed(hint: LiveData>): LiveData { - return Transformations.map(hint, ::processHint) - } - /** Helper for subscribeToAnswerOutcome. */ private fun getAnswerOutcome( answerOutcome: LiveData> @@ -458,30 +400,6 @@ class StateFragmentPresenter @Inject constructor( return ephemeralStateResult.getOrDefault(AnswerOutcome.getDefaultInstance()) } - /** Helper for [subscribeToHint]. */ - private fun processHint(hintResult: AsyncResult): Hint { - if (hintResult.isFailure()) { - oppiaLogger.e( - "StateFragment", - "Failed to retrieve Hint", - hintResult.getErrorOrNull()!! - ) - } - return hintResult.getOrDefault(Hint.getDefaultInstance()) - } - - /** Helper for [subscribeToSolution]. */ - private fun processSolution(solutionResult: AsyncResult): Solution { - if (solutionResult.isFailure()) { - oppiaLogger.e( - "StateFragment", - "Failed to retrieve Solution", - solutionResult.getErrorOrNull()!! - ) - } - return solutionResult.getOrDefault(Solution.getDefaultInstance()) - } - private fun handleSubmitAnswer(answer: UserAnswer) { subscribeToAnswerOutcome(explorationProgressController.submitAnswer(answer)) } @@ -551,4 +469,35 @@ class StateFragmentPresenter @Inject constructor( oppiaClock.getCurrentTimeMs() ) } + + private fun showHintsAndSolutions(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) { + if (!isCurrentStatePendingState) { + // If current state is not the pending top state, hide the hint bulb. + viewModel.setHintOpenedAndUnRevealedVisibility(false) + viewModel.setHintBulbVisibility(false) + } else { + when (helpIndex.indexTypeCase) { + HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX -> { + viewModel.setHintBulbVisibility(true) + viewModel.setHintOpenedAndUnRevealedVisibility(true) + } + HelpIndex.IndexTypeCase.LATEST_REVEALED_HINT_INDEX -> { + viewModel.setHintBulbVisibility(true) + viewModel.setHintOpenedAndUnRevealedVisibility(false) + } + HelpIndex.IndexTypeCase.SHOW_SOLUTION -> { + viewModel.setHintBulbVisibility(true) + viewModel.setHintOpenedAndUnRevealedVisibility(true) + } + HelpIndex.IndexTypeCase.EVERYTHING_REVEALED -> { + viewModel.setHintOpenedAndUnRevealedVisibility(false) + viewModel.setHintBulbVisibility(true) + } + else -> { + viewModel.setHintOpenedAndUnRevealedVisibility(false) + viewModel.setHintBulbVisibility(false) + } + } + } + } } diff --git a/app/src/main/java/org/oppia/android/app/player/state/StatePlayerRecyclerViewAssembler.kt b/app/src/main/java/org/oppia/android/app/player/state/StatePlayerRecyclerViewAssembler.kt index c490971ad17..b0183fc96c0 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/StatePlayerRecyclerViewAssembler.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/StatePlayerRecyclerViewAssembler.kt @@ -22,10 +22,7 @@ import org.oppia.android.app.model.AnswerAndResponse import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.EphemeralState.StateTypeCase import org.oppia.android.app.model.HelpIndex -import org.oppia.android.app.model.HelpIndex.IndexTypeCase.INDEXTYPE_NOT_SET import org.oppia.android.app.model.Interaction -import org.oppia.android.app.model.PendingState -import org.oppia.android.app.model.State import org.oppia.android.app.model.StringList import org.oppia.android.app.model.SubtitledHtml import org.oppia.android.app.model.UserAnswer @@ -34,9 +31,6 @@ import org.oppia.android.app.player.state.StatePlayerRecyclerViewAssembler.Build import org.oppia.android.app.player.state.answerhandling.InteractionAnswerErrorOrAvailabilityCheckReceiver import org.oppia.android.app.player.state.answerhandling.InteractionAnswerHandler import org.oppia.android.app.player.state.answerhandling.InteractionAnswerReceiver -import org.oppia.android.app.player.state.hintsandsolution.DelayShowAdditionalHintsFromWrongAnswerMillis -import org.oppia.android.app.player.state.hintsandsolution.DelayShowAdditionalHintsMillis -import org.oppia.android.app.player.state.hintsandsolution.DelayShowInitialHintMillis import org.oppia.android.app.player.state.itemviewmodel.ContentViewModel import org.oppia.android.app.player.state.itemviewmodel.ContinueInteractionViewModel import org.oppia.android.app.player.state.itemviewmodel.ContinueNavigationButtonViewModel @@ -139,10 +133,7 @@ class StatePlayerRecyclerViewAssembler private constructor( private val interactionViewModelFactoryMap: Map< String, @JvmSuppressWildcards InteractionViewModelFactory>, backgroundCoroutineDispatcher: CoroutineDispatcher, - private val hasConversationView: Boolean, - delayShowInitialHintMs: Long, - delayShowAdditionalHintsMs: Long, - delayShowAdditionalHintsFromWrongAnswerMs: Long + private val hasConversationView: Boolean ) : HtmlParser.CustomOppiaTagActionListener { /** * A list of view models corresponding to past view models that are hidden by default. These are @@ -162,14 +153,6 @@ class StatePlayerRecyclerViewAssembler private constructor( private val lifecycleSafeTimerFactory = LifecycleSafeTimerFactory(backgroundCoroutineDispatcher) - private val hintHandler = HintHandler( - lifecycleSafeTimerFactory, - fragment, - delayShowInitialHintMs, - delayShowAdditionalHintsMs, - delayShowAdditionalHintsFromWrongAnswerMs - ) - /** The most recent content ID read by the audio system. */ private var audioPlaybackContentId: String? = null @@ -217,6 +200,12 @@ class StatePlayerRecyclerViewAssembler private constructor( val interaction = ephemeralState.state.interaction if (ephemeralState.stateTypeCase == StateTypeCase.PENDING_STATE) { + if (playerFeatureSet.hintsAndSolutionsSupport) { + (fragment as ShowHintAvailabilityListener).onHintAvailable( + ephemeralState.pendingState.helpIndex, + isCurrentStatePendingState = true + ) + } addPreviousAnswers( conversationPendingItemList, extraInteractionPendingItemList, @@ -224,9 +213,6 @@ class StatePlayerRecyclerViewAssembler private constructor( /* isCorrectAnswer= */ false, gcsEntityId ) - if (playerFeatureSet.hintsAndSolutionsSupport) { - hintHandler.maybeScheduleShowHint(ephemeralState.state, ephemeralState.pendingState) - } if (playerFeatureSet.interactionSupport) { val interactionItemList = if (isSplitView) extraInteractionPendingItemList else conversationPendingItemList @@ -238,6 +224,14 @@ class StatePlayerRecyclerViewAssembler private constructor( ) } } else if (ephemeralState.stateTypeCase == StateTypeCase.COMPLETED_STATE) { + // Ensure any lingering hints are properly cleared. + if (playerFeatureSet.hintsAndSolutionsSupport) { + (fragment as ShowHintAvailabilityListener).onHintAvailable( + HelpIndex.getDefaultInstance(), + isCurrentStatePendingState = false + ) + } + // Ensure the answer is marked in situations where that's guaranteed (e.g. completed state) // so that the UI always has the correct answer indication, even after configuration changes. isCorrectAnswer.set(true) @@ -248,7 +242,6 @@ class StatePlayerRecyclerViewAssembler private constructor( /* isCorrectAnswer= */ true, gcsEntityId ) - hintHandler.hideHint() } val isTerminalState = ephemeralState.stateTypeCase == StateTypeCase.TERMINAL_STATE @@ -481,12 +474,6 @@ class StatePlayerRecyclerViewAssembler private constructor( } } - /** - * Stops any pending hints from showing, e.g. due to the state being completed. This should only - * be called if hints & solutions support has been enabled. - */ - fun stopHintsFromShowing() = hintHandler.reset() - /** * Toggles whether current audio playback is enabled. This should only be called if voiceover * support has been enabled. @@ -860,10 +847,7 @@ class StatePlayerRecyclerViewAssembler private constructor( private val fragment: Fragment, private val context: Context, private val interactionViewModelFactoryMap: Map, - private val backgroundCoroutineDispatcher: CoroutineDispatcher, - private val delayShowInitialHintMs: Long, - private val delayShowAdditionalHintsMs: Long, - private val delayShowAdditionalHintsFromWrongAnswerMs: Long + private val backgroundCoroutineDispatcher: CoroutineDispatcher ) { private val adapterBuilder = BindableAdapter.MultiTypeBuilder.newBuilder( StateItemViewModel::viewType @@ -1321,10 +1305,7 @@ class StatePlayerRecyclerViewAssembler private constructor( audioUiManagerRetriever, interactionViewModelFactoryMap, backgroundCoroutineDispatcher, - hasConversationView, - delayShowInitialHintMs, - delayShowAdditionalHintsMs, - delayShowAdditionalHintsFromWrongAnswerMs + hasConversationView ) if (playerFeatureSet.conceptCardSupport) { customTagListener.proxyListener = assembler @@ -1339,10 +1320,7 @@ class StatePlayerRecyclerViewAssembler private constructor( private val context: Context, private val interactionViewModelFactoryMap: Map< String, @JvmSuppressWildcards InteractionViewModelFactory>, - @BackgroundDispatcher private val backgroundCoroutineDispatcher: CoroutineDispatcher, - @DelayShowInitialHintMillis private val delayShowInitialHintMs: Long, - @DelayShowAdditionalHintsMillis private val delayShowAdditionalHintsMs: Long, - @DelayShowAdditionalHintsFromWrongAnswerMillis private val additionalAnswerHintDelayMs: Long + @BackgroundDispatcher private val backgroundCoroutineDispatcher: CoroutineDispatcher ) { /** * Returns a new [Builder] for the specified GCS resource bucket information for loading @@ -1356,10 +1334,7 @@ class StatePlayerRecyclerViewAssembler private constructor( fragment, context, interactionViewModelFactoryMap, - backgroundCoroutineDispatcher, - delayShowInitialHintMs, - delayShowAdditionalHintsMs, - additionalAnswerHintDelayMs + backgroundCoroutineDispatcher ) } } @@ -1407,194 +1382,4 @@ class StatePlayerRecyclerViewAssembler private constructor( ) } } - - /** - * Handler for showing hints to the learner after a period of time in the event they submit a - * wrong answer. - * - * # Flow chart for when hints are shown - * - * Submit 1st Submit wrong - * wrong answer answer - * +---+ +---+ - * | | | | - * | v | v - * +-+---+----+ +-+---+-----+ +----------+ - * Initial| No | Wait 60s | | View hint | Hint | - * state | hint +----------->+ Hint +---------->+ consumed | - * +----->+ released | or, submit | available | Wait 30s | | - * | | 2nd wrong | +<----------+ | - * +----------+ answer +----+------+ +----+-----+ - * ^ | - * |Wait 10s | - * | | - * +----+------+ | - * +--->+ No | Submit wrong | - * Submit wrong| | hint | answer | - * answer | | available +<---------------+ - * +----+ | - * +-----------+ - * - * # Logic for selecting a hint - * - * Hints are selected based on the availability of hints to show, and any previous hints that have - * been shown. A new hint will only be made available if its previous hint has been viewed by the - * learner. Hints are always shown in order. If all hints have been exhausted and viewed by the - * user, then the 'hint available' state in the diagram above will trigger the solution to be - * made available to view, if a solution is present. Once the solution is viewed by the learner, - * they will reach a terminal state for hints and no additional hints or solutions will be made - * available. - */ - private class HintHandler( - private val lifecycleSafeTimerFactory: LifecycleSafeTimerFactory, - private val fragment: Fragment, - private val delayShowInitialHintMs: Long, - private val delayShowAdditionalHintsMs: Long, - private val delayShowAdditionalHintsFromWrongAnswerMs: Long - ) { - private var trackedWrongAnswerCount = 0 - private var previousHelpIndex: HelpIndex = HelpIndex.getDefaultInstance() - private var hintSequenceNumber = 0 - private var isHintVisibleInLatestState = false - - /** Resets this handler to prepare it for a new state, cancelling any pending hints. */ - fun reset() { - trackedWrongAnswerCount = 0 - previousHelpIndex = HelpIndex.getDefaultInstance() - // Cancel any potential pending hints by advancing the sequence number. Note that this isn't - // reset to 0 to ensure that all previous hint tasks are cancelled, and new tasks can be - // scheduled without overlapping with past sequence numbers. - hintSequenceNumber++ - isHintVisibleInLatestState = false - } - - /** Hide hint when moving to any previous state. */ - fun hideHint() { - (fragment as ShowHintAvailabilityListener).onHintAvailable( - HelpIndex.getDefaultInstance() - ) - } - - /** - * Handles potentially new wrong answers that were submnitted, and if so schedules a hint to be - * shown to the user if hints are available. - */ - fun maybeScheduleShowHint(state: State, pendingState: PendingState) { - if (state.interaction.hintList.isEmpty()) { - // If this state has no hints to show, do nothing. - return - } - - // If hint was visible in the current state show all previous hints coming back to the current - // state. If any hint was revealed and user move between current and completed states, then - // show those revealed hints back by making icon visible else use the previous help index. - if (isHintVisibleInLatestState) { - if (state.interaction.hintList[previousHelpIndex.hintIndex].hintIsRevealed) { - (fragment as ShowHintAvailabilityListener).onHintAvailable( - HelpIndex.newBuilder().setEverythingRevealed(true).build() - ) - } else { - (fragment as ShowHintAvailabilityListener).onHintAvailable( - previousHelpIndex - ) - } - } - - // Start showing hints after a wrong answer is submitted or if the user appears stuck (e.g. - // doesn't answer after some duration). Note that if there's already a timer to show a hint, - // it will be reset for each subsequent answer. - val nextUnrevealedHintIndex = getNextHintIndexToReveal(state) - val isFirstHint = previousHelpIndex.indexTypeCase == INDEXTYPE_NOT_SET - val wrongAnswerCount = pendingState.wrongAnswerList.size - if (wrongAnswerCount == trackedWrongAnswerCount) { - // If no answers have been submitted, schedule a task to automatically help after a fixed - // amount of time. This will automatically reset if something changes other than answers - // (e.g. revealing a hint), which may trigger more help to become available. - if (isFirstHint) { - // The learner needs to wait longer for the initial hint to show since they need some time - // to read through and consider the question. - scheduleShowHint(delayShowInitialHintMs, nextUnrevealedHintIndex) - } else { - scheduleShowHint(delayShowAdditionalHintsMs, nextUnrevealedHintIndex) - } - } else { - // See if the learner's new wrong answer justifies showing a hint. - if (isFirstHint) { - if (wrongAnswerCount > 1) { - // If more than one answer has been submitted and no hint has yet been shown, show a - // hint immediately since the learner is probably stuck. - showHintImmediately(nextUnrevealedHintIndex) - } - } else { - // Otherwise, always schedule to show a hint on a new wrong answer for subsequent hints. - scheduleShowHint( - delayShowAdditionalHintsFromWrongAnswerMs, - nextUnrevealedHintIndex - ) - } - trackedWrongAnswerCount = wrongAnswerCount - } - } - - /** - * Returns the [HelpIndex] of the next hint or solution that hasn't yet been revealed, or - * default if there is none. - */ - private fun getNextHintIndexToReveal(state: State): HelpIndex { - // Return the index of the first unrevealed hint, or the length of the list if all have been - // revealed. - val hintList = state.interaction.hintList - val solution = state.interaction.solution - - val hasHelp = hintList.isNotEmpty() || solution.hasCorrectAnswer() - val lastUnrevealedHintIndex = hintList.indices.filterNot { idx -> - hintList[idx].hintIsRevealed - }.firstOrNull() - - return if (!hasHelp) { - HelpIndex.getDefaultInstance() - } else if (lastUnrevealedHintIndex != null) { - HelpIndex.newBuilder().setHintIndex(lastUnrevealedHintIndex).build() - } else if (solution.hasCorrectAnswer() && !solution.solutionIsRevealed) { - HelpIndex.newBuilder().setShowSolution(true).build() - } else { - HelpIndex.newBuilder().setEverythingRevealed(true).build() - } - } - - /** - * Schedules to allow the hint of the specified index to be shown after the specified delay, - * cancelling any previously pending hints initiated by calls to this method. - */ - private fun scheduleShowHint(delayMs: Long, helpIndexToShow: HelpIndex) { - val targetSequenceNumber = ++hintSequenceNumber - lifecycleSafeTimerFactory.createTimer(delayMs).observe( - fragment, - Observer { - showHint(targetSequenceNumber, helpIndexToShow) - } - ) - } - - /** - * Immediately indicates the specified hint is ready to be shown, cancelling any previously - * pending hints initiated by calls to [scheduleShowHint]. - */ - private fun showHintImmediately(helpIndexToShow: HelpIndex) { - showHint(++hintSequenceNumber, helpIndexToShow) - } - - private fun showHint(targetSequenceNumber: Int, helpIndexToShow: HelpIndex) { - // Only finish this timer if no other hints were scheduled and no cancellations occurred. - if (targetSequenceNumber == hintSequenceNumber) { - if (previousHelpIndex != helpIndexToShow) { - // Only indicate the hint is available if its index is actually new (including if it - // becomes null such as in the case of the solution becoming available). - (fragment as ShowHintAvailabilityListener).onHintAvailable(helpIndexToShow) - previousHelpIndex = helpIndexToShow - isHintVisibleInLatestState = true - } - } - } - } } diff --git a/app/src/main/java/org/oppia/android/app/player/state/StateViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/StateViewModel.kt index a2e284ae53c..a46208966b1 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/StateViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/StateViewModel.kt @@ -23,8 +23,6 @@ class StateViewModel @Inject constructor() : ObservableViewModel() { val isAudioBarVisible = ObservableField(false) - var newAvailableHintIndex = -1 - var allHintsExhausted = false val isHintBulbVisible = ObservableField(false) val isHintOpenedAndUnRevealed = ObservableField(false) diff --git a/app/src/main/java/org/oppia/android/app/player/state/listener/RouteToHintsAndSolutionListener.kt b/app/src/main/java/org/oppia/android/app/player/state/listener/RouteToHintsAndSolutionListener.kt index 9412a17e999..351e37b35c1 100755 --- a/app/src/main/java/org/oppia/android/app/player/state/listener/RouteToHintsAndSolutionListener.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/listener/RouteToHintsAndSolutionListener.kt @@ -1,10 +1,11 @@ package org.oppia.android.app.player.state.listener +import org.oppia.android.app.model.HelpIndex + /** Listener for when an [ExplorationActivity] should route to a [HintsAndSolution]. */ interface RouteToHintsAndSolutionListener { fun routeToHintsAndSolution( id: String, - newAvailableHintIndex: Int, - allHintsExhausted: Boolean + helpIndex: HelpIndex ) } diff --git a/app/src/main/java/org/oppia/android/app/player/state/listener/ShowHintAvailabilityListener.kt b/app/src/main/java/org/oppia/android/app/player/state/listener/ShowHintAvailabilityListener.kt index d8012967f89..5571d06c5ae 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/listener/ShowHintAvailabilityListener.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/listener/ShowHintAvailabilityListener.kt @@ -4,6 +4,12 @@ import org.oppia.android.app.model.HelpIndex /** Callback interface for when hints can be made available to the learner. */ interface ShowHintAvailabilityListener { - /** Called when a hint is available to be shown, or null if all hints have been revealed. */ - fun onHintAvailable(helpIndex: HelpIndex) + /** + * Called when a hint is available to be shown, or null if all hints have been revealed. + * + * @param helpIndex the latest hints/solution state + * @param isCurrentStatePendingState whether the current state being viewed by the learner is + * pending and should have hints enabled + */ + fun onHintAvailable(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) } diff --git a/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivity.kt b/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivity.kt index eb2a058d54c..881b333aef0 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivity.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivity.kt @@ -8,6 +8,7 @@ import org.oppia.android.app.hintsandsolution.HintsAndSolutionDialogFragment import org.oppia.android.app.hintsandsolution.HintsAndSolutionListener import org.oppia.android.app.hintsandsolution.RevealHintListener import org.oppia.android.app.hintsandsolution.RevealSolutionInterface +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.State import org.oppia.android.app.player.audio.AudioButtonListener import org.oppia.android.app.player.exploration.HintsAndSolutionExplorationManagerListener @@ -90,23 +91,21 @@ class StateFragmentTestActivity : override fun routeToHintsAndSolution( explorationId: String, - newAvailableHintIndex: Int, - allHintsExhausted: Boolean + helpIndex: HelpIndex ) { if (getHintsAndSolution() == null) { val hintsAndSolutionFragment = HintsAndSolutionDialogFragment.newInstance( explorationId, - newAvailableHintIndex, - allHintsExhausted + state, + helpIndex ) - hintsAndSolutionFragment.loadState(state) hintsAndSolutionFragment.showNow(supportFragmentManager, TAG_HINTS_AND_SOLUTION_DIALOG) } } - override fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - stateFragmentTestActivityPresenter.revealHint(saveUserChoice, hintIndex) + override fun revealHint(hintIndex: Int) { + stateFragmentTestActivityPresenter.revealHint(hintIndex) } override fun revealSolution() { diff --git a/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivityPresenter.kt index 5185c910bd2..feeb36fc10e 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivityPresenter.kt @@ -71,8 +71,7 @@ class StateFragmentTestActivityPresenter @Inject constructor( fun scrollToTop() = getStateFragment()?.scrollToTop() - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) = - getStateFragment()?.revealHint(saveUserChoice, hintIndex) + fun revealHint(hintIndex: Int) = getStateFragment()?.revealHint(hintIndex) fun revealSolution() = getStateFragment()?.revealSolution() diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt index d85334e54a1..8662b6b31ce 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt @@ -8,6 +8,7 @@ import org.oppia.android.app.hintsandsolution.HintsAndSolutionDialogFragment import org.oppia.android.app.hintsandsolution.HintsAndSolutionListener import org.oppia.android.app.hintsandsolution.RevealHintListener import org.oppia.android.app.hintsandsolution.RevealSolutionInterface +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.State import org.oppia.android.app.player.exploration.TAG_HINTS_AND_SOLUTION_DIALOG import org.oppia.android.app.player.state.listener.RouteToHintsAndSolutionListener @@ -81,8 +82,8 @@ class QuestionPlayerActivity : } } - override fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - questionPlayerActivityPresenter.revealHint(saveUserChoice, hintIndex) + override fun revealHint(hintIndex: Int) { + questionPlayerActivityPresenter.revealHint(hintIndex) } override fun revealSolution() { @@ -97,17 +98,15 @@ class QuestionPlayerActivity : override fun routeToHintsAndSolution( questionId: String, - newAvailableHintIndex: Int, - allHintsExhausted: Boolean + helpIndex: HelpIndex ) { if (getHintsAndSolution() == null) { val hintsAndSolutionDialogFragment = HintsAndSolutionDialogFragment.newInstance( questionId, - newAvailableHintIndex, - allHintsExhausted + state, + helpIndex ) - hintsAndSolutionDialogFragment.loadState(state) hintsAndSolutionDialogFragment.showNow(supportFragmentManager, TAG_HINTS_AND_SOLUTION_DIALOG) } } diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt index 286a363222d..48b91f7b732 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt @@ -155,12 +155,12 @@ class QuestionPlayerActivityPresenter @Inject constructor( ) as QuestionPlayerFragment? } - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { + fun revealHint(hintIndex: Int) { val questionPlayerFragment = activity.supportFragmentManager.findFragmentByTag( TAG_QUESTION_PLAYER_FRAGMENT ) as QuestionPlayerFragment - questionPlayerFragment.revealHint(saveUserChoice, hintIndex) + questionPlayerFragment.revealHint(hintIndex) } fun revealSolution() { diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragment.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragment.kt index 399a5388cbf..9196f19e102 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragment.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragment.kt @@ -72,10 +72,13 @@ class QuestionPlayerFragment : ) = questionPlayerFragmentPresenter.updateSubmitButton(pendingAnswerError, inputAnswerAvailable) + override fun onHintAvailable(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) = + questionPlayerFragmentPresenter.onHintAvailable(helpIndex, isCurrentStatePendingState) + fun handleKeyboardAction() = questionPlayerFragmentPresenter.handleKeyboardAction() - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - questionPlayerFragmentPresenter.revealHint(saveUserChoice, hintIndex) + fun revealHint(hintIndex: Int) { + questionPlayerFragmentPresenter.revealHint(hintIndex) } fun revealSolution() { @@ -83,7 +86,4 @@ class QuestionPlayerFragment : } fun dismissConceptCard() = questionPlayerFragmentPresenter.dismissConceptCard() - - override fun onHintAvailable(helpIndex: HelpIndex) = - questionPlayerFragmentPresenter.onHintAvailable(helpIndex) } diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragmentPresenter.kt index 1783ae49bd8..0b6883c6e47 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragmentPresenter.kt @@ -18,8 +18,6 @@ import org.oppia.android.app.model.EphemeralQuestion import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.HelpIndex -import org.oppia.android.app.model.Hint -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.State import org.oppia.android.app.model.UserAnswer import org.oppia.android.app.player.state.ConfettiConfig.MINI_CONFETTI_BURST @@ -67,6 +65,7 @@ class QuestionPlayerFragmentPresenter @Inject constructor( private lateinit var recyclerViewAssembler: StatePlayerRecyclerViewAssembler private lateinit var questionId: String private lateinit var currentQuestionState: State + private lateinit var helpIndex: HelpIndex fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { binding = QuestionPlayerFragmentBinding.inflate( @@ -95,28 +94,19 @@ class QuestionPlayerFragmentPresenter @Inject constructor( binding.hintsAndSolutionFragmentContainer.setOnClickListener { routeToHintsAndSolutionListener.routeToHintsAndSolution( questionId, - questionViewModel.newAvailableHintIndex, - questionViewModel.allHintsExhausted + helpIndex ) } subscribeToCurrentQuestion() return binding.root } - fun revealHint(saveUserChoice: Boolean, hintIndex: Int) { - subscribeToHint( - questionAssessmentProgressController.submitHintIsRevealed( - currentQuestionState, - saveUserChoice, - hintIndex - ) - ) + fun revealHint(hintIndex: Int) { + subscribeToHintSolution(questionAssessmentProgressController.submitHintIsRevealed(hintIndex)) } fun revealSolution() { - subscribeToSolution( - questionAssessmentProgressController.submitSolutionIsRevealed(currentQuestionState) - ) + subscribeToHintSolution(questionAssessmentProgressController.submitSolutionIsRevealed()) } fun dismissConceptCard() { @@ -127,28 +117,6 @@ class QuestionPlayerFragmentPresenter @Inject constructor( } } - fun onHintAvailable(helpIndex: HelpIndex) { - when (helpIndex.indexTypeCase) { - HelpIndex.IndexTypeCase.HINT_INDEX, HelpIndex.IndexTypeCase.SHOW_SOLUTION -> { - if (helpIndex.indexTypeCase == HelpIndex.IndexTypeCase.HINT_INDEX) { - questionViewModel.newAvailableHintIndex = helpIndex.hintIndex - } - questionViewModel.allHintsExhausted = - helpIndex.indexTypeCase == HelpIndex.IndexTypeCase.SHOW_SOLUTION - questionViewModel.setHintOpenedAndUnRevealedVisibility(true) - questionViewModel.setHintBulbVisibility(true) - } - HelpIndex.IndexTypeCase.EVERYTHING_REVEALED -> { - questionViewModel.setHintOpenedAndUnRevealedVisibility(false) - questionViewModel.setHintBulbVisibility(true) - } - else -> { - questionViewModel.setHintOpenedAndUnRevealedVisibility(false) - questionViewModel.setHintBulbVisibility(false) - } - } - } - fun handleAnswerReadyForSubmission(answer: UserAnswer) { // An interaction has indicated that an answer is ready for submission. handleSubmitAnswer(answer) @@ -200,6 +168,11 @@ class QuestionPlayerFragmentPresenter @Inject constructor( fun handleKeyboardAction() = onSubmitButtonClicked() + fun onHintAvailable(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) { + this.helpIndex = helpIndex + showHintsAndSolutions(helpIndex, isCurrentStatePendingState) + } + private fun subscribeToCurrentQuestion() { ephemeralQuestionLiveData.observe( fragment, @@ -290,7 +263,6 @@ class QuestionPlayerFragmentPresenter @Inject constructor( Observer { result -> recyclerViewAssembler.isCorrectAnswer.set(result.isCorrectAnswer) if (result.isCorrectAnswer) { - recyclerViewAssembler.stopHintsFromShowing() questionViewModel.setHintBulbVisibility(false) recyclerViewAssembler.showCelebrationOnCorrectAnswer() } else { @@ -300,76 +272,23 @@ class QuestionPlayerFragmentPresenter @Inject constructor( ) } - /** - * This function listens to the result of RevealHint. - * Whenever a hint is revealed using QuestionAssessmentProgressController.submitHintIsRevealed function, - * this function will wait for the response from that function and based on which we can move to next state. - */ - private fun subscribeToHint(hintResultLiveData: LiveData>) { - val hintLiveData = getHintIsRevealed(hintResultLiveData) - hintLiveData.observe( + /** Subscribes to the result of requesting to show a hint or solution. */ + private fun subscribeToHintSolution(resultLiveData: LiveData>) { + resultLiveData.observe( fragment, - Observer { result -> - // If the hint was revealed remove dot and radar. - if (result.hintIsRevealed) { - questionViewModel.setHintOpenedAndUnRevealedVisibility(false) - } - } - ) - } - - /** - * This function listens to the result of RevealSolution. - * Whenever a hint is revealed using QuestionAssessmentProgressController.submitHintIsRevealed function, - * this function will wait for the response from that function and based on which we can move to next state. - */ - private fun subscribeToSolution(solutionResultLiveData: LiveData>) { - val solutionLiveData = getSolutionIsRevealed(solutionResultLiveData) - solutionLiveData.observe( - fragment, - Observer { result -> - // If the hint was revealed remove dot and radar. - if (result.solutionIsRevealed) { + { result -> + if (result.isFailure()) { + oppiaLogger.e( + "StateFragment", "Failed to retrieve hint/solution", result.getErrorOrNull()!! + ) + } else { + // If the hint/solution, was revealed remove dot and radar. questionViewModel.setHintOpenedAndUnRevealedVisibility(false) } } ) } - /** Helper for [subscribeToSolution]. */ - private fun getSolutionIsRevealed(hint: LiveData>): LiveData { - return Transformations.map(hint, ::processSolution) - } - - /** Helper for [subscribeToHint]. */ - private fun getHintIsRevealed(hint: LiveData>): LiveData { - return Transformations.map(hint, ::processHint) - } - - /** Helper for [subscribeToHint]. */ - private fun processHint(hintResult: AsyncResult): Hint { - if (hintResult.isFailure()) { - oppiaLogger.e( - "QuestionPlayerFragment", - "Failed to retrieve Hint", - hintResult.getErrorOrNull()!! - ) - } - return hintResult.getOrDefault(Hint.getDefaultInstance()) - } - - /** Helper for [subscribeToSolution]. */ - private fun processSolution(solutionResult: AsyncResult): Solution { - if (solutionResult.isFailure()) { - oppiaLogger.e( - "QuestionPlayerFragment", - "Failed to retrieve Solution", - solutionResult.getErrorOrNull()!! - ) - } - return solutionResult.getOrDefault(Solution.getDefaultInstance()) - } - /** Helper for subscribeToAnswerOutcome. */ private fun processAnsweredQuestionOutcome( answeredQuestionOutcomeResult: AsyncResult @@ -440,4 +359,35 @@ class QuestionPlayerFragmentPresenter @Inject constructor( ) ) } + + private fun showHintsAndSolutions(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) { + if (!isCurrentStatePendingState) { + // If current question state is not the pending top question state, hide the hint bulb. + questionViewModel.setHintOpenedAndUnRevealedVisibility(false) + questionViewModel.setHintBulbVisibility(false) + } else { + when (helpIndex.indexTypeCase) { + HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX -> { + questionViewModel.setHintBulbVisibility(true) + questionViewModel.setHintOpenedAndUnRevealedVisibility(true) + } + HelpIndex.IndexTypeCase.LATEST_REVEALED_HINT_INDEX -> { + questionViewModel.setHintBulbVisibility(true) + questionViewModel.setHintOpenedAndUnRevealedVisibility(false) + } + HelpIndex.IndexTypeCase.SHOW_SOLUTION -> { + questionViewModel.setHintBulbVisibility(true) + questionViewModel.setHintOpenedAndUnRevealedVisibility(true) + } + HelpIndex.IndexTypeCase.EVERYTHING_REVEALED -> { + questionViewModel.setHintOpenedAndUnRevealedVisibility(false) + questionViewModel.setHintBulbVisibility(true) + } + else -> { + questionViewModel.setHintOpenedAndUnRevealedVisibility(false) + questionViewModel.setHintBulbVisibility(false) + } + } + } + } } diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerViewModel.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerViewModel.kt index 36172c6be5d..a81352b4b55 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerViewModel.kt @@ -25,8 +25,6 @@ class QuestionPlayerViewModel @Inject constructor() : ObservableViewModel() { val isAtEndOfSession = ObservableBoolean(false) private val canSubmitAnswer = ObservableField(false) - var newAvailableHintIndex = -1 - var allHintsExhausted = false val isHintBulbVisible = ObservableField(false) val isHintOpenedAndUnRevealed = ObservableField(false) diff --git a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt index a2e893c67a0..34904d1bc12 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt @@ -57,7 +57,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profile.ProfileChooserActivity import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.settings.profile.ProfileListActivity @@ -77,6 +76,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -701,9 +702,9 @@ class AdministratorControlsActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AppVersionActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AppVersionActivityTest.kt index c581ae1d0a0..a158aabd083 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AppVersionActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AppVersionActivityTest.kt @@ -39,7 +39,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -57,6 +56,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -264,9 +265,9 @@ class AppVersionActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/completedstorylist/CompletedStoryListActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/completedstorylist/CompletedStoryListActivityTest.kt index f8dfbecb4c7..56a7ac87747 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/completedstorylist/CompletedStoryListActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/completedstorylist/CompletedStoryListActivityTest.kt @@ -40,7 +40,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -58,6 +57,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -484,9 +485,9 @@ class CompletedStoryListActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/customview/LessonThumbnailImageViewTest.kt b/app/src/sharedTest/java/org/oppia/android/app/customview/LessonThumbnailImageViewTest.kt index 27da76f80dd..010973725cc 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/customview/LessonThumbnailImageViewTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/customview/LessonThumbnailImageViewTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.LessonThumbnail -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.LessonThumbnailImageViewTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -41,6 +40,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -142,9 +143,9 @@ class LessonThumbnailImageViewTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/databinding/MarginBindingAdaptersTest.kt b/app/src/sharedTest/java/org/oppia/android/app/databinding/MarginBindingAdaptersTest.kt index b63b801e945..8ef4e30f15e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/databinding/MarginBindingAdaptersTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/databinding/MarginBindingAdaptersTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.databinding.MarginBindingAdapters.setLayoutMarginEn import org.oppia.android.app.databinding.MarginBindingAdapters.setLayoutMarginStart import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.MarginBindingAdaptersTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -52,6 +51,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -280,9 +281,9 @@ class MarginBindingAdaptersTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerMarginBindingAdaptersTest.kt b/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerMarginBindingAdaptersTest.kt index 2d7dc4296e1..036f0bcee4e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerMarginBindingAdaptersTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerMarginBindingAdaptersTest.kt @@ -38,7 +38,6 @@ import org.oppia.android.app.databinding.StateAssemblerMarginBindingAdapters.set import org.oppia.android.app.databinding.StateAssemblerMarginBindingAdapters.setQuestionViewMargin import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.StateAssemblerMarginBindingAdaptersTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -54,6 +53,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -468,9 +469,9 @@ class StateAssemblerMarginBindingAdaptersTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerPaddingBindingAdaptersTest.kt b/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerPaddingBindingAdaptersTest.kt index 3ed13a226ca..3a0b85d3925 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerPaddingBindingAdaptersTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/databinding/StateAssemblerPaddingBindingAdaptersTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.databinding.StateAssemblerPaddingBindingAdapters.se import org.oppia.android.app.databinding.StateAssemblerPaddingBindingAdapters.setQuestionViewPadding import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.StateAssemblerPaddingBindingAdaptersTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -52,6 +51,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -466,9 +467,9 @@ class StateAssemblerPaddingBindingAdaptersTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/databinding/ViewBindingAdaptersTest.kt b/app/src/sharedTest/java/org/oppia/android/app/databinding/ViewBindingAdaptersTest.kt index b65ad9f8fcc..e290b675c6b 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/databinding/ViewBindingAdaptersTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/databinding/ViewBindingAdaptersTest.kt @@ -33,7 +33,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.databinding.ViewBindingAdapters.setRotationAnimation import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.ViewBindingAdaptersTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -49,6 +48,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -200,9 +201,9 @@ class ViewBindingAdaptersTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityTest.kt index 6170a72da2f..a653df63e97 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityTest.kt @@ -32,7 +32,6 @@ import androidx.test.rule.ActivityTestRule import com.google.common.truth.Truth.assertThat import dagger.Component import org.hamcrest.Matchers -import org.hamcrest.Matchers.not import org.junit.After import org.junit.Before import org.junit.Rule @@ -46,7 +45,6 @@ import org.oppia.android.app.application.ApplicationInjector import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -62,6 +60,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -268,9 +268,9 @@ class DeveloperOptionsActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsFragmentTest.kt index 8c964816d9d..c98b1eb896c 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/DeveloperOptionsFragmentTest.kt @@ -44,7 +44,6 @@ import org.oppia.android.app.devoptions.markstoriescompleted.MarkStoriesComplete import org.oppia.android.app.devoptions.marktopicscompleted.MarkTopicsCompletedActivity import org.oppia.android.app.devoptions.testing.DeveloperOptionsTestActivity import org.oppia.android.app.devoptions.vieweventlogs.ViewEventLogsActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -61,6 +60,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -518,9 +519,9 @@ class DeveloperOptionsFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedActivityTest.kt index 30c718e37e5..c89fd732c7d 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedActivityTest.kt @@ -28,7 +28,6 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.markchapterscompleted.MarkChaptersCompletedActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -44,6 +43,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -157,9 +158,9 @@ class MarkChaptersCompletedActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt index 45912109290..0fdb0b8c350 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkChaptersCompletedFragmentTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.markchapterscompleted.testing.MarkChaptersCompletedTestActivity import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -861,9 +862,9 @@ class MarkChaptersCompletedFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedActivityTest.kt index 28ea84c657b..2e5720da20f 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedActivityTest.kt @@ -28,7 +28,6 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.markstoriescompleted.MarkStoriesCompletedActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -44,6 +43,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -157,9 +158,9 @@ class MarkStoriesCompletedActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt index e53c4be7da3..2678fe285ad 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkStoriesCompletedFragmentTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.markstoriescompleted.testing.MarkStoriesCompletedTestActivity import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -562,9 +563,9 @@ class MarkStoriesCompletedFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedActivityTest.kt index dec78d84777..3a1793e8836 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedActivityTest.kt @@ -28,7 +28,6 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.marktopicscompleted.MarkTopicsCompletedActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -44,6 +43,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -157,9 +158,9 @@ class MarkTopicsCompletedActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt index 1b01e3ba03c..3602311aa8b 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/MarkTopicsCompletedFragmentTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.marktopicscompleted.testing.MarkTopicsCompletedTestActivity import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -532,9 +533,9 @@ class MarkTopicsCompletedFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsActivityTest.kt index 6e77301e052..a4eefff8481 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsActivityTest.kt @@ -29,7 +29,6 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.vieweventlogs.ViewEventLogsActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -45,6 +44,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -145,9 +146,9 @@ class ViewEventLogsActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, DebugLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsFragmentTest.kt index 907bd4fada2..dd4c1d73a0e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/ViewEventLogsFragmentTest.kt @@ -32,7 +32,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.vieweventlogs.testing.ViewEventLogsTestActivity import org.oppia.android.app.model.EventLog.EventAction -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.hasItemCount import org.oppia.android.app.shim.ViewBindingShimModule @@ -50,6 +49,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.OppiaLogger @@ -600,9 +601,9 @@ class ViewEventLogsFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, DebugLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeActivityTest.kt index de502d3addf..a7e26b12350 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeActivityTest.kt @@ -29,7 +29,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -45,6 +44,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -152,10 +153,10 @@ class ForceNetworkTypeActivityTest { ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) /** [ApplicationComponent] for [ForceNetworkTypeActivityTest]. */ diff --git a/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeFragmentTest.kt index 1f7d99e74c3..a3257f73e45 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/devoptions/forcenetworktype/ForceNetworkTypeFragmentTest.kt @@ -33,7 +33,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.devoptions.forcenetworktype.testing.ForceNetworkTypeTestActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -50,6 +49,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -368,10 +369,10 @@ class ForceNetworkTypeFragmentTest { ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) /** [ApplicationComponent] for [ForceNetworkTypeFragmentTest]. */ diff --git a/app/src/sharedTest/java/org/oppia/android/app/faq/FAQListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/faq/FAQListFragmentTest.kt index 3586cb7b0fa..a9159cadc88 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/faq/FAQListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/faq/FAQListFragmentTest.kt @@ -38,7 +38,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.faq.FAQListActivity import org.oppia.android.app.help.faq.faqsingle.FAQSingleActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -56,6 +55,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -191,9 +192,9 @@ class FAQListFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/faq/FAQSingleActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/faq/FAQSingleActivityTest.kt index d6453358abe..d42829534a2 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/faq/FAQSingleActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/faq/FAQSingleActivityTest.kt @@ -35,7 +35,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.faq.faqsingle.FAQSingleActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -50,6 +49,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -189,9 +190,9 @@ class FAQSingleActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/faq/FaqListActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/faq/FaqListActivityTest.kt index eb27d00d4b9..460cf7e1514 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/faq/FaqListActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/faq/FaqListActivityTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.faq.FAQListActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -122,9 +123,9 @@ class FaqListActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/help/HelpActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/help/HelpActivityTest.kt index 72038c68462..f732abf2dcd 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/help/HelpActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/help/HelpActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.data.backends.gae.NetworkModule @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -125,9 +126,9 @@ class HelpActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt index 24bce84d003..8a69379a5db 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/help/HelpFragmentTest.kt @@ -45,7 +45,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.faq.FAQListActivity import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -63,6 +62,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -588,9 +589,9 @@ class HelpFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt index 6640fe8bdf6..7e82d4013f3 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt @@ -50,7 +50,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedActivity import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profile.ProfileChooserActivity import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView @@ -73,6 +72,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1458,9 +1459,9 @@ class HomeActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt index cfe16d7d131..1b40dc09f94 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt @@ -52,7 +52,6 @@ import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedActivity import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedFragment import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.hasGridItemCount import org.oppia.android.app.shim.ViewBindingShimModule @@ -71,6 +70,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1291,9 +1292,9 @@ class RecentlyPlayedFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/TopicSummaryViewModelTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/TopicSummaryViewModelTest.kt index ae2f6a4e1de..a767ef375a1 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/TopicSummaryViewModelTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/TopicSummaryViewModelTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.topiclist.TopicSummaryViewModel import org.oppia.android.app.model.TopicSummary -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.HomeFragmentTestActivity @@ -40,6 +39,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -336,10 +337,10 @@ class TopicSummaryViewModelTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/WelcomeViewModelTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/WelcomeViewModelTest.kt index cbffc404c3c..00ce5999afa 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/WelcomeViewModelTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/WelcomeViewModelTest.kt @@ -22,7 +22,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.HomeFragmentTestActivity @@ -40,6 +39,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -331,10 +332,10 @@ class WelcomeViewModelTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryListViewModelTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryListViewModelTest.kt index 4c989d7199f..c168b097884 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryListViewModelTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryListViewModelTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.PromotedActivityList import org.oppia.android.app.model.PromotedStory import org.oppia.android.app.model.PromotedStoryList -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.HomeFragmentTestActivity @@ -41,6 +40,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -340,10 +341,10 @@ class PromotedStoryListViewModelTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryViewModelTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryViewModelTest.kt index 018fb185d66..f9c91f3bb0e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryViewModelTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/promotedlist/PromotedStoryViewModelTest.kt @@ -22,7 +22,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.PromotedStory -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.HomeFragmentTestActivity @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -351,10 +352,10 @@ class PromotedStoryViewModelTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/sharedTest/java/org/oppia/android/app/mydownloads/MyDownloadsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/mydownloads/MyDownloadsFragmentTest.kt index 669a52a00e0..30208ef29e9 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/mydownloads/MyDownloadsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/mydownloads/MyDownloadsFragmentTest.kt @@ -32,7 +32,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.EspressoTestsMatchers.matchCurrentTabTitle @@ -48,6 +47,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -203,9 +204,9 @@ class MyDownloadsFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingActivityTest.kt index 1159cf1a981..4e8187fb419 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -121,9 +122,9 @@ class OnboardingActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingFragmentTest.kt index b30e81f8a87..c2697588be9 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/onboarding/OnboardingFragmentTest.kt @@ -47,7 +47,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profile.ProfileChooserActivity import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -64,6 +63,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -655,9 +656,9 @@ class OnboardingFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicListActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicListActivityTest.kt index fe9d68c8bd4..f4fb3b994bf 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicListActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicListActivityTest.kt @@ -39,7 +39,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -57,6 +56,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -428,9 +429,9 @@ class OngoingTopicListActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageActivityTest.kt index eae20456450..2a7c2f8c7a6 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -131,9 +132,9 @@ class AppLanguageActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt index 9f4a17f5a83..b863bdc3928 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest.kt @@ -30,7 +30,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -47,6 +46,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -227,9 +228,9 @@ class AppLanguageFragmentTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, ApplicationStartupListenerModule::class, RatioInputModule::class, HintsAndSolutionConfigModule::class, - WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, - LogUploadWorkerModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, + HintsAndSolutionProdModule::class, WorkManagerConfigurationModule::class, + FirebaseLogUploaderModule::class, LogUploadWorkerModule::class, FakeOppiaClockModule::class, + PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageActivityTest.kt index aa6495839f0..d8822822af9 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -131,9 +132,9 @@ class AudioLanguageActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt index 01044869d34..093f29044b3 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt @@ -29,7 +29,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -46,6 +45,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -220,9 +221,9 @@ class AudioLanguageFragmentTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, ApplicationStartupListenerModule::class, RatioInputModule::class, HintsAndSolutionConfigModule::class, - WorkManagerConfigurationModule::class, LogUploadWorkerModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, + HintsAndSolutionProdModule::class, WorkManagerConfigurationModule::class, + LogUploadWorkerModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, + PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/OptionsActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/OptionsActivityTest.kt index 64e2500f147..8ccfb0c7283 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/OptionsActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/OptionsActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -123,9 +124,9 @@ class OptionsActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt index 0d29eee063c..e08d3bee380 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt @@ -42,7 +42,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -59,6 +58,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -622,9 +623,9 @@ class OptionsFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt index 87b1ac58a02..3a8f7a777c9 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -131,9 +132,9 @@ class ReadingTextSizeActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt index cb84012a020..c28e93d26f8 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -286,9 +287,9 @@ class ReadingTextSizeFragmentTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, ApplicationStartupListenerModule::class, RatioInputModule::class, HintsAndSolutionConfigModule::class, - WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, - LogUploadWorkerModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, + HintsAndSolutionProdModule::class, WorkManagerConfigurationModule::class, + FirebaseLogUploaderModule::class, LogUploadWorkerModule::class, FakeOppiaClockModule::class, + PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] diff --git a/app/src/sharedTest/java/org/oppia/android/app/parser/CustomBulletSpanTest.kt b/app/src/sharedTest/java/org/oppia/android/app/parser/CustomBulletSpanTest.kt index acb0c5708b6..69a3d1746b3 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/parser/CustomBulletSpanTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/parser/CustomBulletSpanTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -225,10 +226,10 @@ class CustomBulletSpanTest { ViewBindingShimModule::class, RatioInputModule::class, PlatformParameterModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) diff --git a/app/src/sharedTest/java/org/oppia/android/app/parser/HtmlParserTest.kt b/app/src/sharedTest/java/org/oppia/android/app/parser/HtmlParserTest.kt index 81b675ede1d..ab46d6e526e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/parser/HtmlParserTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/parser/HtmlParserTest.kt @@ -50,7 +50,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.HtmlParserTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -66,6 +65,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -625,9 +626,9 @@ class HtmlParserTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt index 290391f19a8..a481e973669 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt @@ -44,7 +44,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.AudioFragmentTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -62,6 +61,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -451,9 +452,9 @@ class AudioFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt index 846c18e5f18..9e05d19f6d4 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt @@ -62,7 +62,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.HelpActivity import org.oppia.android.app.options.OptionsActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.ExplorationInjectionActivity import org.oppia.android.app.topic.PracticeTabModule @@ -81,6 +80,8 @@ import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.ExplorationDataController import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageDatabaseSize +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1615,9 +1616,9 @@ class ExplorationActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, TestExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/state/StateFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/state/StateFragmentTest.kt index b0c0648a366..9c4b548db0b 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/player/state/StateFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/player/state/StateFragmentTest.kt @@ -71,7 +71,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigFastShowTestModule import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.ViewType.CONTENT import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.ViewType.CONTINUE_INTERACTION @@ -109,6 +108,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigFastShowTestModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -2005,9 +2006,10 @@ class StateFragmentTest { LogStorageModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, - HintsAndSolutionConfigFastShowTestModule::class, WorkManagerConfigurationModule::class, - LogUploadWorkerModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, - PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, + HintsAndSolutionConfigFastShowTestModule::class, HintsAndSolutionProdModule::class, + WorkManagerConfigurationModule::class, LogUploadWorkerModule::class, + FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, + DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/AddProfileActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/AddProfileActivityTest.kt index 6cc62995dcd..0679fe061c7 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profile/AddProfileActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profile/AddProfileActivityTest.kt @@ -60,7 +60,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -76,6 +75,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1624,9 +1625,9 @@ class AddProfileActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/AdminAuthActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/AdminAuthActivityTest.kt index b3fa35a31e2..70519429f2c 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profile/AdminAuthActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profile/AdminAuthActivityTest.kt @@ -48,7 +48,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -64,6 +63,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -635,9 +636,9 @@ class AdminAuthActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/AdminPinActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/AdminPinActivityTest.kt index fc47801132f..2d8bf72dfc0 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profile/AdminPinActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profile/AdminPinActivityTest.kt @@ -56,7 +56,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -72,6 +71,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1086,9 +1087,9 @@ class AdminPinActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt index 52ca23619b6..ed111cf3c44 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profile/PinPasswordActivityTest.kt @@ -50,7 +50,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.HomeActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.EspressoTestsMatchers.withDrawable @@ -67,6 +66,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1088,9 +1089,9 @@ class PinPasswordActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserFragmentTest.kt index 2ad54259eea..0b3b471dbb5 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserFragmentTest.kt @@ -42,7 +42,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.drawer.NAVIGATION_PROFILE_ID_ARGUMENT_KEY -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -60,6 +59,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -500,9 +501,9 @@ class ProfileChooserFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfilePictureActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfilePictureActivityTest.kt index 7c163df809d..6f9e4b3f40f 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfilePictureActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfilePictureActivityTest.kt @@ -28,7 +28,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -43,6 +42,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -135,9 +136,9 @@ class ProfilePictureActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressActivityTest.kt index 53d267df1ef..98f55150bdc 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -125,9 +126,9 @@ class ProfileProgressActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressFragmentTest.kt index b027d3cc51a..157b1fced96 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/profileprogress/ProfileProgressFragmentTest.kt @@ -56,7 +56,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedActivity import org.oppia.android.app.model.ProfileId import org.oppia.android.app.ongoingtopiclist.OngoingTopicListActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -74,6 +73,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -732,8 +733,8 @@ class ProfileProgressFragmentTest { ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, - HintsAndSolutionConfigModule::class, FirebaseLogUploaderModule::class, - FakeOppiaClockModule::class, PracticeTabModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, + FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class diff --git a/app/src/sharedTest/java/org/oppia/android/app/recyclerview/BindableAdapterTest.kt b/app/src/sharedTest/java/org/oppia/android/app/recyclerview/BindableAdapterTest.kt index 6411ed46bc9..a2bfb7b0573 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/recyclerview/BindableAdapterTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/recyclerview/BindableAdapterTest.kt @@ -40,7 +40,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.fragment.FragmentComponent import org.oppia.android.app.fragment.FragmentModule import org.oppia.android.app.fragment.FragmentScope -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.player.state.itemviewmodel.InteractionViewModelModule import org.oppia.android.app.recyclerview.BindableAdapter.MultiTypeBuilder import org.oppia.android.app.recyclerview.BindableAdapter.SingleTypeBuilder @@ -72,6 +71,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -729,9 +730,9 @@ class BindableAdapterTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditActivityTest.kt index 237ff33f32f..632c9a54731 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileEditActivityTest.kt @@ -42,7 +42,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -58,6 +57,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -547,9 +548,9 @@ class ProfileEditActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListActivityTest.kt index 88c8293c0f7..92098c9a264 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -121,9 +122,9 @@ class ProfileListActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListFragmentTest.kt index cdc19bc9a1b..b100ef96747 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileListFragmentTest.kt @@ -35,7 +35,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -359,9 +360,9 @@ class ProfileListFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileRenameActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileRenameActivityTest.kt index 81043c325ba..d46a21810df 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileRenameActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileRenameActivityTest.kt @@ -46,7 +46,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -62,6 +61,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -459,9 +460,9 @@ class ProfileRenameActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileResetPinActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileResetPinActivityTest.kt index 9f8b9cbb187..ffc15b7c1e8 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileResetPinActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/settings/profile/ProfileResetPinActivityTest.kt @@ -48,7 +48,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -64,6 +63,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1014,9 +1015,9 @@ class ProfileResetPinActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/splash/SplashActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/splash/SplashActivityTest.kt index 62a9792808a..37e8c70056f 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/splash/SplashActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/splash/SplashActivityTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.onboarding.OnboardingActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profile.ProfileChooserActivity import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -52,6 +51,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.AppStartupStateController import org.oppia.android.domain.onboarding.testing.ExpirationMetaDataRetrieverTestModule import org.oppia.android.domain.onboarding.testing.FakeExpirationMetaDataRetriever @@ -299,11 +300,11 @@ class SplashActivityTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverTestModule::class, ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, HintsAndSolutionConfigModule::class, - LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, LogUploadWorkerModule::class, + WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt index 50590a11ef6..eecb1567328 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt @@ -37,7 +37,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.player.exploration.ExplorationActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -52,6 +51,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -205,9 +206,9 @@ class StoryActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt index 6253b5584e5..776f67a013c 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt @@ -64,7 +64,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.hasItemCount @@ -83,6 +82,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -721,9 +722,9 @@ class StoryFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/DragDropTestActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/DragDropTestActivityTest.kt index d073b996a38..066a1acf58c 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/DragDropTestActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/DragDropTestActivityTest.kt @@ -25,7 +25,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.DragAndDropItemFacilitator import org.oppia.android.app.recyclerview.OnDragEndedListener import org.oppia.android.app.recyclerview.OnItemDragListener @@ -48,6 +47,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -194,9 +195,9 @@ class DragDropTestActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/ImageRegionSelectionInteractionViewTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/ImageRegionSelectionInteractionViewTest.kt index 63e0903dfad..bdac7f39851 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/ImageRegionSelectionInteractionViewTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/ImageRegionSelectionInteractionViewTest.kt @@ -38,7 +38,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.player.state.ImageRegionSelectionInteractionView import org.oppia.android.app.player.state.StateFragment -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.DefaultRegionClickedEvent @@ -58,6 +57,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -292,9 +293,9 @@ class ImageRegionSelectionInteractionViewTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/InputInteractionViewTestActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/InputInteractionViewTestActivityTest.kt index 5b66226822d..643fc577ef1 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/InputInteractionViewTestActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/InputInteractionViewTestActivityTest.kt @@ -38,7 +38,6 @@ import org.oppia.android.app.customview.interaction.RatioInputInteractionView import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.InteractionObject -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -1010,9 +1011,9 @@ class InputInteractionViewTestActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityDebugTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityDebugTest.kt index 80ff5acdf2a..e994d946378 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityDebugTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityDebugTest.kt @@ -59,7 +59,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsActivity import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.drawer.NavigationDrawerItem -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -75,6 +74,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -414,9 +415,9 @@ class NavigationDrawerActivityDebugTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt index 661f92079f2..900bf35f1ab 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt @@ -65,7 +65,6 @@ import org.oppia.android.app.drawer.NavigationDrawerItem import org.oppia.android.app.help.HelpActivity import org.oppia.android.app.model.ProfileId import org.oppia.android.app.mydownloads.MyDownloadsActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profile.ProfileChooserActivity import org.oppia.android.app.profileprogress.ProfileProgressActivity import org.oppia.android.app.shim.ViewBindingShimModule @@ -83,6 +82,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -963,9 +964,9 @@ class NavigationDrawerActivityProdTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt index 519a588c674..59f10da1833 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt @@ -27,7 +27,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ReadingTextSize -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.FontSizeMatcher.Companion.withFontSize @@ -43,6 +42,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -171,9 +172,9 @@ class TestFontScaleConfigurationUtilActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/TopicTestActivityForStoryTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/TopicTestActivityForStoryTest.kt index b508b6a9273..879d4d064fd 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/TopicTestActivityForStoryTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/TopicTestActivityForStoryTest.kt @@ -29,7 +29,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -49,6 +48,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -169,9 +170,9 @@ class TopicTestActivityForStoryTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListActivityTest.kt index 11c056c658b..2e056824bfb 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListActivityTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.LicenseListActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -133,9 +134,9 @@ class LicenseListActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt index 7514c90d8d7..bfb847d5d31 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseListFragmentTest.kt @@ -38,7 +38,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.LicenseListActivity import org.oppia.android.app.help.thirdparty.LicenseTextViewerActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -55,6 +54,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -347,9 +348,9 @@ class LicenseListFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt index 86b416e94c7..63263ab88b2 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt @@ -25,7 +25,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.LicenseListActivity import org.oppia.android.app.help.thirdparty.LicenseTextViewerActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -40,6 +39,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -142,9 +143,9 @@ class LicenseTextViewerActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerFragmentTest.kt index 713a5c8d7bd..2940e786c8e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerFragmentTest.kt @@ -29,7 +29,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.LicenseTextViewerActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -45,6 +44,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -325,9 +326,9 @@ class LicenseTextViewerFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListActivityTest.kt index 2638d0f56c4..f5c2f7b2388 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListActivityTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -130,9 +131,9 @@ class ThirdPartyDependencyListActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListFragmentTest.kt index 9d37c8961e4..974e8cce3fb 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/ThirdPartyDependencyListFragmentTest.kt @@ -37,7 +37,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.thirdparty.LicenseListActivity import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -54,6 +53,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -457,9 +458,9 @@ class ThirdPartyDependencyListFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/TopicActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/TopicActivityTest.kt index 0b25a972a5e..9106248222f 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/TopicActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/TopicActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.domain.classify.InteractionsModule import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule @@ -37,6 +36,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -131,9 +132,9 @@ class TopicActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt index deab6324c89..ca4bb116b1a 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt @@ -41,7 +41,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.utility.EspressoTestsMatchers.matchCurrentTabTitle @@ -58,6 +57,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -592,9 +593,9 @@ class TopicFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt index 134e1b29c55..676182635f3 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/conceptcard/ConceptCardFragmentTest.kt @@ -39,7 +39,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.ConceptCardFragmentTestActivity import org.oppia.android.app.topic.PracticeTabModule @@ -56,6 +55,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -294,9 +295,9 @@ class ConceptCardFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/info/TopicInfoFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/info/TopicInfoFragmentTest.kt index 70e7c64e00a..a7508bb475b 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/info/TopicInfoFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/info/TopicInfoFragmentTest.kt @@ -42,7 +42,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.topic.TopicActivity @@ -60,6 +59,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -417,9 +418,9 @@ class TopicInfoFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt index 49f71e0f6be..0b808ef1816 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt @@ -46,7 +46,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -69,6 +68,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -698,9 +699,9 @@ class TopicLessonsFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/practice/TopicPracticeFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/practice/TopicPracticeFragmentTest.kt index 7ba6d90164a..5a520e58ff3 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/practice/TopicPracticeFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/practice/TopicPracticeFragmentTest.kt @@ -40,7 +40,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.EnablePracticeTab @@ -61,6 +60,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -404,9 +405,9 @@ class TopicPracticeFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt index dd908817755..57e744d3886 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt @@ -53,7 +53,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigFastShowTestModule import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.ViewType.FEEDBACK import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.ViewType.SELECTION_INTERACTION @@ -73,6 +72,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigFastShowTestModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -515,11 +516,11 @@ class QuestionPlayerActivityTest { NumberWithUnitsRuleModule::class, NumericInputRuleModule::class, TextInputRuleModule::class, DragDropSortInputModule::class, ImageClickInputModule::class, InteractionsModule::class, GcsResourceModule::class, GlideImageLoaderModule::class, ImageParsingModule::class, - HtmlParserEntityTypeModule::class, TestLogReportingModule::class, - AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, + HtmlParserEntityTypeModule::class, TestLogReportingModule::class, LogStorageModule::class, + AccessibilityTestModule::class, CachingTestModule::class, RatioInputModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, ApplicationStartupListenerModule::class, - RatioInputModule::class, HintsAndSolutionConfigFastShowTestModule::class, + HintsAndSolutionConfigFastShowTestModule::class, HintsAndSolutionProdModule::class, WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, LogUploadWorkerModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/revision/TopicRevisionFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/revision/TopicRevisionFragmentTest.kt index eb61369a6e9..427b9d16ff7 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/revision/TopicRevisionFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/revision/TopicRevisionFragmentTest.kt @@ -39,7 +39,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -62,6 +61,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -301,9 +302,9 @@ class TopicRevisionFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt index f12b983bb51..4b03917d167 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -143,9 +144,9 @@ class RevisionCardActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardFragmentTest.kt index a22f8f931cd..1112756c21b 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardFragmentTest.kt @@ -50,7 +50,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.HelpActivity import org.oppia.android.app.options.OptionsActivity import org.oppia.android.app.player.exploration.ExplorationActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.topic.revisioncard.RevisionCardActivity.Companion.createRevisionCardActivityIntent // ktlint-disable max-line-length @@ -67,6 +66,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -427,9 +428,9 @@ class RevisionCardFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/utility/RatioExtensionsTest.kt b/app/src/sharedTest/java/org/oppia/android/app/utility/RatioExtensionsTest.kt index 99f0a54b8e6..cfcbbe28c4c 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/utility/RatioExtensionsTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/utility/RatioExtensionsTest.kt @@ -20,7 +20,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.RatioExpression -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -35,6 +34,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -117,9 +118,9 @@ class RatioExtensionsTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughActivityTest.kt index 4a3f31c1035..00702ee0fea 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughActivityTest.kt @@ -28,7 +28,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -45,6 +44,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -176,9 +177,9 @@ class WalkthroughActivityTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughFinalFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughFinalFragmentTest.kt index 54debd48fe5..26bd5b4d817 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughFinalFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughFinalFragmentTest.kt @@ -34,7 +34,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -52,6 +51,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -261,9 +262,9 @@ class WalkthroughFinalFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughTopicListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughTopicListFragmentTest.kt index 15d374ce82c..fa4f2f1814a 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughTopicListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughTopicListFragmentTest.kt @@ -35,7 +35,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -53,6 +52,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -287,9 +288,9 @@ class WalkthroughTopicListFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughWelcomeFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughWelcomeFragmentTest.kt index 9d69210fd89..a0a625d0dda 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughWelcomeFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/walkthrough/WalkthroughWelcomeFragmentTest.kt @@ -32,7 +32,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.ProfileId import org.oppia.android.app.onboarding.OnboardingActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape @@ -48,6 +47,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -184,9 +185,9 @@ class WalkthroughWelcomeFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/home/HomeActivityLocalTest.kt b/app/src/test/java/org/oppia/android/app/home/HomeActivityLocalTest.kt index 4673a6bddf9..b27f72099f5 100644 --- a/app/src/test/java/org/oppia/android/app/home/HomeActivityLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/home/HomeActivityLocalTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.ACTIVITYCONTEXT_NOT_SET -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -40,6 +39,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -127,10 +128,10 @@ class HomeActivityLocalTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/parser/StringToFractionParserTest.kt b/app/src/test/java/org/oppia/android/app/parser/StringToFractionParserTest.kt index d15ac9d34e9..82332129b1c 100644 --- a/app/src/test/java/org/oppia/android/app/parser/StringToFractionParserTest.kt +++ b/app/src/test/java/org/oppia/android/app/parser/StringToFractionParserTest.kt @@ -20,7 +20,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.Fraction -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -35,6 +34,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -436,9 +437,9 @@ class StringToFractionParserTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/parser/StringToRatioParserTest.kt b/app/src/test/java/org/oppia/android/app/parser/StringToRatioParserTest.kt index 93c144e8cd0..126dd817553 100644 --- a/app/src/test/java/org/oppia/android/app/parser/StringToRatioParserTest.kt +++ b/app/src/test/java/org/oppia/android/app/parser/StringToRatioParserTest.kt @@ -20,7 +20,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.RatioExpression -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -35,6 +34,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -212,9 +213,9 @@ class StringToRatioParserTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt b/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt index 1fb42e3cb06..cc3dbc17d5d 100644 --- a/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.EXPLORATION_CONTEXT -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.ExplorationInjectionActivity @@ -41,6 +40,8 @@ import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.ExplorationDataController import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -191,10 +192,10 @@ class ExplorationActivityLocalTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt b/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt index ef450d6d43d..9729b22e11a 100644 --- a/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt @@ -57,7 +57,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.hintsandsolution.TAG_REVEAL_SOLUTION_DIALOG import org.oppia.android.app.player.exploration.TAG_HINTS_AND_SOLUTION_DIALOG -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.ViewType.CONTINUE_INTERACTION import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.ViewType.CONTINUE_NAVIGATION_BUTTON @@ -84,6 +83,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -764,6 +765,60 @@ class StateFragmentLocalTest { } } + @Test + fun testStateFragment_nextState_viewFirstHint_configChange_secondHintIsNotAvailableImmediately() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { + startPlayingExploration() + playThroughState1() + produceAndViewFirstHint() + + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.dot_hint)).check(matches(not(isDisplayed()))) + } + } + + @Test + fun testStateFragment_nextState_viewFirstHint_configChange_wait30Seconds_secondHintIsAvailable() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { + startPlayingExploration() + playThroughState1() + produceAndViewFirstHint() + + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + // Since no answer was submitted after viewing the first hint, the second hint should be + // revealed in 30 seconds. + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(30)) + onView(withId(R.id.dot_hint)).check(matches(isDisplayed())) + } + } + + @Test + fun testStateFragment_nextState_newHintAvailable_configChange_newHintIsAvailable() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { + startPlayingExploration() + playThroughState1() + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(60)) + onView(withId(R.id.dot_hint)).check(matches(isDisplayed())) + onView(isRoot()).perform(orientationLandscape()) + testCoroutineDispatchers.runCurrent() + onView(withId(R.id.dot_hint)).check(matches(isDisplayed())) + } + } + + @Test + fun testStateFragment_nextState_viewFirstHint_prevState_wait30seconds_newHintIsNotAvailable() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { + startPlayingExploration() + playThroughState1() + produceAndViewFirstHint() + clickPreviousStateNavigationButton() + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(30)) + onView(withId(R.id.dot_hint)).check(matches(not(isDisplayed()))) + } + } + @Test fun testStateFragment_nextState_viewFourHints_wait10seconds_noNewHintIsAvailable() { launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { @@ -1598,9 +1653,9 @@ class StateFragmentLocalTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/profile/ProfileChooserFragmentLocalTest.kt b/app/src/test/java/org/oppia/android/app/profile/ProfileChooserFragmentLocalTest.kt index d66f6253b17..3c2cae49e61 100644 --- a/app/src/test/java/org/oppia/android/app/profile/ProfileChooserFragmentLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/profile/ProfileChooserFragmentLocalTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.ACTIVITYCONTEXT_NOT_SET import org.oppia.android.app.model.EventLog.EventAction import org.oppia.android.app.model.EventLog.Priority -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -117,11 +118,11 @@ class ProfileChooserFragmentLocalTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, HintsAndSolutionConfigModule::class, - LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, LogUploadWorkerModule::class, + WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/story/StoryActivityLocalTest.kt b/app/src/test/java/org/oppia/android/app/story/StoryActivityLocalTest.kt index f25de6660d1..351c45bc4b7 100644 --- a/app/src/test/java/org/oppia/android/app/story/StoryActivityLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/story/StoryActivityLocalTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.STORY_CONTEXT -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -39,6 +38,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -139,9 +140,9 @@ class StoryActivityLocalTest { QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, ImageClickInputModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/testing/CompletedStoryListSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/CompletedStoryListSpanTest.kt index 9907cf23d1c..9d14e36e59e 100644 --- a/app/src/test/java/org/oppia/android/app/testing/CompletedStoryListSpanTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/CompletedStoryListSpanTest.kt @@ -25,7 +25,6 @@ import org.oppia.android.app.completedstorylist.CompletedStoryListActivity import org.oppia.android.app.completedstorylist.CompletedStoryListFragment.Companion.COMPLETED_STORY_LIST_FRAGMENT_TAG import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -41,6 +40,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -149,10 +150,10 @@ class CompletedStoryListSpanTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt index 0bf361c0523..5adfd8da1d0 100644 --- a/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt @@ -24,7 +24,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.HomeActivity -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.hasGridItemCount import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule @@ -41,6 +40,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -163,10 +164,10 @@ class HomeSpanTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/OngoingTopicListSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/OngoingTopicListSpanTest.kt index a04ad8e3207..c7054f530b6 100644 --- a/app/src/test/java/org/oppia/android/app/testing/OngoingTopicListSpanTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/OngoingTopicListSpanTest.kt @@ -26,7 +26,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.ongoingtopiclist.OngoingTopicListActivity import org.oppia.android.app.ongoingtopiclist.OngoingTopicListFragment -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -42,6 +41,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -160,10 +161,10 @@ class OngoingTopicListSpanTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/PlatformParameterIntegrationTest.kt b/app/src/test/java/org/oppia/android/app/testing/PlatformParameterIntegrationTest.kt index 47b19a972d8..df8b0904fbf 100644 --- a/app/src/test/java/org/oppia/android/app/testing/PlatformParameterIntegrationTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/PlatformParameterIntegrationTest.kt @@ -21,7 +21,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.PlatformParameter -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -36,6 +35,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -139,9 +140,9 @@ class PlatformParameterIntegrationTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/testing/ProfileChooserSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/ProfileChooserSpanTest.kt index a082dd5edf5..c27243eaa6a 100644 --- a/app/src/test/java/org/oppia/android/app/testing/ProfileChooserSpanTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/ProfileChooserSpanTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profile.ProfileChooserFragment import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule @@ -40,6 +39,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -362,10 +363,10 @@ class ProfileChooserSpanTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/ProfileProgressSpanCount.kt b/app/src/test/java/org/oppia/android/app/testing/ProfileProgressSpanCount.kt index 6cb9d62b220..3784f80cd24 100644 --- a/app/src/test/java/org/oppia/android/app/testing/ProfileProgressSpanCount.kt +++ b/app/src/test/java/org/oppia/android/app/testing/ProfileProgressSpanCount.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.profileprogress.ProfileProgressActivity import org.oppia.android.app.profileprogress.ProfileProgressFragment import org.oppia.android.app.shim.IntentFactoryShimModule @@ -41,6 +40,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -145,10 +146,10 @@ class ProfileProgressSpanCount { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class, ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/RecentlyPlayedSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/RecentlyPlayedSpanTest.kt index 264c0e3f1cb..e68676ef524 100644 --- a/app/src/test/java/org/oppia/android/app/testing/RecentlyPlayedSpanTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/RecentlyPlayedSpanTest.kt @@ -26,7 +26,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedActivity import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.hasGridItemCount import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule @@ -43,6 +42,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -281,10 +282,10 @@ class RecentlyPlayedSpanTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/TopicRevisionSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/TopicRevisionSpanTest.kt index 2a2f7191166..8e0a39b4dbd 100644 --- a/app/src/test/java/org/oppia/android/app/testing/TopicRevisionSpanTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/TopicRevisionSpanTest.kt @@ -23,7 +23,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -40,6 +39,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -146,10 +147,10 @@ class TopicRevisionSpanTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/administratorcontrols/AdministratorControlsFragmentTest.kt b/app/src/test/java/org/oppia/android/app/testing/administratorcontrols/AdministratorControlsFragmentTest.kt index 3e0865ffaed..08e8371074d 100644 --- a/app/src/test/java/org/oppia/android/app/testing/administratorcontrols/AdministratorControlsFragmentTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/administratorcontrols/AdministratorControlsFragmentTest.kt @@ -34,7 +34,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.settings.profile.ProfileListActivity import org.oppia.android.app.settings.profile.ProfileListFragment import org.oppia.android.app.shim.ViewBindingShimModule @@ -51,6 +50,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -204,9 +205,9 @@ class AdministratorControlsFragmentTest { HtmlParserEntityTypeModule::class, QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/testing/options/OptionsFragmentTest.kt b/app/src/test/java/org/oppia/android/app/testing/options/OptionsFragmentTest.kt index 8bf2e1259aa..61a4429114a 100644 --- a/app/src/test/java/org/oppia/android/app/testing/options/OptionsFragmentTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/options/OptionsFragmentTest.kt @@ -28,7 +28,6 @@ import org.oppia.android.app.options.AppLanguageFragment import org.oppia.android.app.options.AudioLanguageFragment import org.oppia.android.app.options.OptionsActivity import org.oppia.android.app.options.ReadingTextSizeFragment -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -44,6 +43,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -203,9 +204,9 @@ class OptionsFragmentTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, ApplicationStartupListenerModule::class, RatioInputModule::class, HintsAndSolutionConfigModule::class, - WorkManagerConfigurationModule::class, LogUploadWorkerModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, + HintsAndSolutionProdModule::class, WorkManagerConfigurationModule::class, + LogUploadWorkerModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, + PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] diff --git a/app/src/test/java/org/oppia/android/app/testing/player/split/PlayerSplitScreenTesting.kt b/app/src/test/java/org/oppia/android/app/testing/player/split/PlayerSplitScreenTesting.kt index 9f5a4987a2c..f3cf2520666 100644 --- a/app/src/test/java/org/oppia/android/app/testing/player/split/PlayerSplitScreenTesting.kt +++ b/app/src/test/java/org/oppia/android/app/testing/player/split/PlayerSplitScreenTesting.kt @@ -20,7 +20,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.ExplorationTestActivity @@ -38,6 +37,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -174,10 +175,10 @@ class PlayerSplitScreenTesting { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class, ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/testing/player/state/StateFragmentAccessibilityTest.kt b/app/src/test/java/org/oppia/android/app/testing/player/state/StateFragmentAccessibilityTest.kt index 599cc2254ef..c2c9baeb554 100644 --- a/app/src/test/java/org/oppia/android/app/testing/player/state/StateFragmentAccessibilityTest.kt +++ b/app/src/test/java/org/oppia/android/app/testing/player/state/StateFragmentAccessibilityTest.kt @@ -27,7 +27,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.player.state.StateFragment -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.player.state.testing.StateFragmentTestActivity import org.oppia.android.app.recyclerview.RecyclerViewMatcher import org.oppia.android.app.shim.IntentFactoryShimModule @@ -45,6 +44,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -187,10 +188,10 @@ class StateFragmentAccessibilityTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/topic/info/TopicInfoFragmentLocalTest.kt b/app/src/test/java/org/oppia/android/app/topic/info/TopicInfoFragmentLocalTest.kt index d2a79d6af36..630a0889e66 100644 --- a/app/src/test/java/org/oppia/android/app/topic/info/TopicInfoFragmentLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/topic/info/TopicInfoFragmentLocalTest.kt @@ -21,7 +21,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.TOPIC_CONTEXT -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.topic.TopicActivity @@ -37,6 +36,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -127,9 +128,9 @@ class TopicInfoFragmentLocalTest { QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, ImageClickInputModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentLocalTest.kt b/app/src/test/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentLocalTest.kt index 8d11a7a7a8f..b6e5bc5d31d 100644 --- a/app/src/test/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentLocalTest.kt @@ -20,7 +20,6 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.app.topic.TopicActivity @@ -36,6 +35,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -129,9 +130,9 @@ class TopicLessonsFragmentLocalTest { QuestionModule::class, TestLogReportingModule::class, AccessibilityTestModule::class, ImageClickInputModule::class, LogStorageModule::class, CachingTestModule::class, PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, - ViewBindingShimModule::class, RatioInputModule::class, + ViewBindingShimModule::class, RatioInputModule::class, WorkManagerConfigurationModule::class, ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, - WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, diff --git a/app/src/test/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityLocalTest.kt b/app/src/test/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityLocalTest.kt index dd8303f4fd6..7aa2760f0f8 100644 --- a/app/src/test/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityLocalTest.kt @@ -36,7 +36,6 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -52,6 +51,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -394,11 +395,11 @@ class QuestionPlayerActivityLocalTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, ApplicationStartupListenerModule::class, RatioInputModule::class, HintsAndSolutionConfigModule::class, - LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, LogUploadWorkerModule::class, + WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/app/src/test/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityLocalTest.kt b/app/src/test/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityLocalTest.kt index 7c8f24a3251..e90f1d298b2 100644 --- a/app/src/test/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityLocalTest.kt @@ -21,7 +21,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.REVISION_CARD_CONTEXT -import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule import org.oppia.android.domain.classify.InteractionsModule @@ -36,6 +35,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule @@ -121,11 +122,11 @@ class RevisionCardActivityLocalTest { PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, ViewBindingShimModule::class, RatioInputModule::class, ApplicationStartupListenerModule::class, HintsAndSolutionConfigModule::class, - LogUploadWorkerModule::class, WorkManagerConfigurationModule::class, - FirebaseLogUploaderModule::class, FakeOppiaClockModule::class, PracticeTabModule::class, - DeveloperOptionsStarterModule::class, DeveloperOptionsModule::class, - ExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class, - NetworkConnectionDebugUtilModule::class + HintsAndSolutionProdModule::class, LogUploadWorkerModule::class, + WorkManagerConfigurationModule::class, FirebaseLogUploaderModule::class, + FakeOppiaClockModule::class, PracticeTabModule::class, DeveloperOptionsStarterModule::class, + DeveloperOptionsModule::class, ExplorationStorageModule::class, + NetworkConnectionUtilDebugModule::class, NetworkConnectionDebugUtilModule::class ] ) interface TestApplicationComponent : ApplicationComponent { diff --git a/domain/BUILD.bazel b/domain/BUILD.bazel index b04aa785256..34ce410458e 100755 --- a/domain/BUILD.bazel +++ b/domain/BUILD.bazel @@ -28,6 +28,11 @@ DOMAIN_ASSETS = generate_assets_list_from_text_protos( "5NWuolNcwH6e", "k2bQ7z5XHNbK", "tIoSb3HZFN6e", + "test_single_interactive_state_exp_no_hints_no_solution", + "test_single_interactive_state_exp_with_hints_and_solution", + "test_single_interactive_state_exp_with_one_hint_and_solution", + "test_single_interactive_state_exp_with_one_hint_and_no_solution", + "test_single_interactive_state_exp_with_only_solution", ], skills_file_names = [ "skills", @@ -131,6 +136,7 @@ TEST_DEPS = [ "//third_party:androidx_arch_core_core-testing", "//third_party:androidx_test_ext_junit", "//third_party:androidx_work_work-testing", + "//third_party:com_google_truth_extensions_truth-liteproto-extension", "//third_party:com_google_truth_truth", "//third_party:org_jetbrains_kotlin_kotlin-reflect", "//third_party:org_jetbrains_kotlin_kotlin-test-junit", diff --git a/domain/build.gradle b/domain/build.gradle index 5cca1e185b6..ac67c4aa974 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -84,6 +84,7 @@ dependencies { 'androidx.test.ext:junit:1.1.1', 'androidx.work:work-testing:2.4.0', 'com.google.dagger:dagger:2.24', + 'com.google.truth.extensions:truth-liteproto-extension:0.43', 'com.google.truth:truth:0.43', 'com.squareup.okhttp3:mockwebserver:4.1.0', 'junit:junit:4.12', diff --git a/domain/src/main/assets/test_single_interactive_state_exp_no_hints_no_solution.json b/domain/src/main/assets/test_single_interactive_state_exp_no_hints_no_solution.json new file mode 100644 index 00000000000..d0e7a3b959e --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_no_hints_no_solution.json @@ -0,0 +1,104 @@ +{ + "exploration_id": "test_single_interactive_state_exp_no_hints_no_solution", + "version": 1, + "exploration": { + "init_state_name": "Text", + "states": { + "Text": { + "content": { + "content_id": "content", + "html": "

In which language does Oppia mean 'to learn'?

" + }, + "interaction": { + "id": "TextInput", + "customization_args": { + "rows": { + "value": 1.0 + }, + "placeholder": { + "value": { + "content_id": "ca_placeholder_0", + "unicode_str": "Enter a language" + } + } + }, + "answer_groups": [{ + "rule_specs": [{ + "rule_type": "Equals", + "inputs": { + "x": { + "contentId": "", + "normalizedStrSet": ["finnish"] + } + } + }], + "outcome": { + "dest": "End", + "feedback": { + "content_id": "feedback_1", + "html": "

Correct!

" + }, + "labelled_as_correct": false + } + }], + "default_outcome": { + "dest": "Text", + "feedback": { + "content_id": "default_outcome", + "html": "

Not quite. Try again (or maybe use a search engine).

" + }, + "labelled_as_correct": false + }, + "hints": [], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {} + } + } + }, + "End": { + "content": { + "content_id": "content", + "html": "Congratulations, you have finished!" + }, + "param_changes": [], + "interaction": { + "id": "EndExploration", + "customization_args": { + "recommendedExplorationIds": { + "value": [] + } + }, + "answer_groups": [], + "default_outcome": null, + "hints": [], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {} + } + }, + "written_translations": { + "translations_mapping": { + "content": {} + } + } + } + }, + "objective": "Test exploration.", + "language_code": "en", + "title": "Prototype exploration without hints or a solution" + } +} diff --git a/domain/src/main/assets/test_single_interactive_state_exp_no_hints_no_solution.textproto b/domain/src/main/assets/test_single_interactive_state_exp_no_hints_no_solution.textproto new file mode 100644 index 00000000000..fd6bc4539a4 --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_no_hints_no_solution.textproto @@ -0,0 +1,123 @@ +id: "test_single_interactive_state_exp_no_hints_no_solution" +states { + key: "Text" + value { + name: "Text" + recorded_voiceovers { + key: "feedback_1" + value { + } + } + recorded_voiceovers { + key: "content" + value { + } + } + recorded_voiceovers { + key: "default_outcome" + value { + } + } + content { + html: "

In which language does Oppia mean \'to learn\'?

" + content_id: "content" + } + written_translations { + key: "feedback_1" + value { + } + } + written_translations { + key: "content" + value { + } + } + written_translations { + key: "default_outcome" + value { + } + } + interaction { + id: "TextInput" + answer_groups { + outcome { + dest_state_name: "End" + feedback { + html: "

Correct!

" + content_id: "feedback_1" + } + } + rule_specs { + input { + key: "x" + value { + translatable_set_of_normalized_string { + content_id: "" + normalized_strings: "finnish" + } + } + } + rule_type: "Equals" + } + } + default_outcome { + dest_state_name: "Text" + feedback { + html: "

Not quite. Try again (or maybe use a search engine).

" + content_id: "default_outcome" + } + } + customization_args { + key: "rows" + value { + signed_int: 1 + } + } + customization_args { + key: "placeholder" + value { + custom_schema_value { + subtitled_html { + html: "Enter a language" + content_id: "ca_placeholder_0" + } + } + } + } + } + } +} +states { + key: "End" + value { + name: "End" + recorded_voiceovers { + key: "content" + value { + } + } + content { + html: "Congratulations, you have finished!" + content_id: "content" + } + written_translations { + key: "content" + value { + } + } + interaction { + id: "EndExploration" + customization_args { + key: "recommendedExplorationIds" + value { + schema_object_list { + } + } + } + } + } +} +init_state_name: "Text" +objective: "Test exploration." +title: "Prototype exploration without hints or a solution" +language_code: "en" diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_hints_and_solution.json b/domain/src/main/assets/test_single_interactive_state_exp_with_hints_and_solution.json new file mode 100644 index 00000000000..323d604f3da --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_hints_and_solution.json @@ -0,0 +1,127 @@ +{ + "exploration_id": "test_single_interactive_state_exp_with_hints_and_solution", + "version": 1, + "exploration": { + "init_state_name": "Text", + "states": { + "Text": { + "content": { + "content_id": "content", + "html": "

In which language does Oppia mean 'to learn'?

" + }, + "interaction": { + "id": "TextInput", + "customization_args": { + "rows": { + "value": 1.0 + }, + "placeholder": { + "value": { + "content_id": "ca_placeholder_0", + "unicode_str": "Enter a language" + } + } + }, + "answer_groups": [{ + "rule_specs": [{ + "rule_type": "Equals", + "inputs": { + "x": { + "contentId": "", + "normalizedStrSet": ["finnish"] + } + } + }], + "outcome": { + "dest": "End", + "feedback": { + "content_id": "feedback_1", + "html": "

Correct!

" + }, + "labelled_as_correct": false + } + }], + "default_outcome": { + "dest": "Text", + "feedback": { + "content_id": "default_outcome", + "html": "

Not quite. Try again (or maybe use a search engine).

" + }, + "labelled_as_correct": false + }, + "hints": [{ + "hint_content": { + "content_id": "hint_1", + "html": "

Hint: 'Oppia' is not English.

" + } + }, { + "hint_content": { + "content_id": "hint_2", + "html": "

Try looking for nordic countries in Europe.

" + } + }], + "solution": { + "answer_is_exclusive": false, + "correct_answer": "Finnish", + "explanation": { + "content_id": "solution", + "html": "

'Oppia' is translated from Finnish.

" + } + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "hint_1": {}, + "hint_2": {}, + "solution": {} + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "hint_1": {}, + "hint_2": {}, + "solution": {} + } + } + }, + "End": { + "content": { + "content_id": "content", + "html": "Congratulations, you have finished!" + }, + "param_changes": [], + "interaction": { + "id": "EndExploration", + "customization_args": { + "recommendedExplorationIds": { + "value": [] + } + }, + "answer_groups": [], + "default_outcome": null, + "hints": [], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {} + } + }, + "written_translations": { + "translations_mapping": { + "content": {} + } + } + } + }, + "objective": "Test exploration.", + "language_code": "en", + "title": "Prototype exploration with multiple hints and a solution" + } +} diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_hints_and_solution.textproto b/domain/src/main/assets/test_single_interactive_state_exp_with_hints_and_solution.textproto new file mode 100644 index 00000000000..b1d36f1d760 --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_hints_and_solution.textproto @@ -0,0 +1,175 @@ +id: "test_single_interactive_state_exp_with_hints_and_solution" +states { + key: "Text" + value { + name: "Text" + recorded_voiceovers { + key: "feedback_1" + value { + } + } + recorded_voiceovers { + key: "content" + value { + } + } + recorded_voiceovers { + key: "default_outcome" + value { + } + } + recorded_voiceovers { + key: "solution" + value { + } + } + recorded_voiceovers { + key: "hint_1" + value { + } + } + recorded_voiceovers { + key: "hint_2" + value { + } + } + content { + html: "

In which language does Oppia mean \'to learn\'?

" + content_id: "content" + } + written_translations { + key: "feedback_1" + value { + } + } + written_translations { + key: "content" + value { + } + } + written_translations { + key: "default_outcome" + value { + } + } + written_translations { + key: "solution" + value { + } + } + written_translations { + key: "hint_1" + value { + } + } + written_translations { + key: "hint_2" + value { + } + } + interaction { + id: "TextInput" + answer_groups { + outcome { + dest_state_name: "End" + feedback { + html: "

Correct!

" + content_id: "feedback_1" + } + } + rule_specs { + input { + key: "x" + value { + translatable_set_of_normalized_string { + content_id: "" + normalized_strings: "finnish" + } + } + } + rule_type: "Equals" + } + } + solution { + interaction_id: "TextInput" + correct_answer { + correct_answer: "Finnish" + } + explanation { + html: "

'Oppia' is translated from Finnish.

" + content_id: "solution" + } + } + hint { + hint_content { + html: "

Hint: 'Oppia' is not English.

" + content_id: "hint_1" + } + } + hint { + hint_content { + html: "

Try looking for nordic countries in Europe.

" + content_id: "hint_2" + } + } + default_outcome { + dest_state_name: "Text" + feedback { + html: "

Not quite. Try again (or maybe use a search engine).

" + content_id: "default_outcome" + } + } + customization_args { + key: "rows" + value { + signed_int: 1 + } + } + customization_args { + key: "placeholder" + value { + custom_schema_value { + subtitled_html { + html: "Enter a language" + content_id: "ca_placeholder_0" + } + } + } + } + } + } +} +states { + key: "End" + value { + name: "End" + recorded_voiceovers { + key: "content" + value { + } + } + content { + html: "Congratulations, you have finished!" + content_id: "content" + } + written_translations { + key: "content" + value { + } + } + interaction { + id: "EndExploration" + customization_args { + key: "recommendedExplorationIds" + value { + schema_object_list { + } + } + } + } + } +} +init_state_name: "Text" +objective: "Test exploration." +title: "Prototype exploration with multiple hints and a solution" +language_code: "en" diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_no_solution.json b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_no_solution.json new file mode 100644 index 00000000000..68cb3565371 --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_no_solution.json @@ -0,0 +1,111 @@ +{ + "exploration_id": "test_single_interactive_state_exp_with_one_hint_and_no_solution", + "version": 1, + "exploration": { + "init_state_name": "Text", + "states": { + "Text": { + "content": { + "content_id": "content", + "html": "

In which language does Oppia mean 'to learn'?

" + }, + "interaction": { + "id": "TextInput", + "customization_args": { + "rows": { + "value": 1.0 + }, + "placeholder": { + "value": { + "content_id": "ca_placeholder_0", + "unicode_str": "Enter a language" + } + } + }, + "answer_groups": [{ + "rule_specs": [{ + "rule_type": "Equals", + "inputs": { + "x": { + "contentId": "", + "normalizedStrSet": ["finnish"] + } + } + }], + "outcome": { + "dest": "End", + "feedback": { + "content_id": "feedback_1", + "html": "

Correct!

" + }, + "labelled_as_correct": false + } + }], + "default_outcome": { + "dest": "Text", + "feedback": { + "content_id": "default_outcome", + "html": "

Not quite. Try again (or maybe use a search engine).

" + }, + "labelled_as_correct": false + }, + "hints": [{ + "hint_content": { + "content_id": "hint_1", + "html": "

Hint: 'Oppia' is not English.

" + } + }], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "hint_1": {} + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "hint_1": {} + } + } + }, + "End": { + "content": { + "content_id": "content", + "html": "Congratulations, you have finished!" + }, + "param_changes": [], + "interaction": { + "id": "EndExploration", + "customization_args": { + "recommendedExplorationIds": { + "value": [] + } + }, + "answer_groups": [], + "default_outcome": null, + "hints": [], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {} + } + }, + "written_translations": { + "translations_mapping": { + "content": {} + } + } + } + }, + "objective": "Test exploration.", + "language_code": "en", + "title": "Prototype exploration with one hint and no solution" + } +} diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_no_solution.textproto b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_no_solution.textproto new file mode 100644 index 00000000000..b00a23ff8aa --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_no_solution.textproto @@ -0,0 +1,139 @@ +id: "test_single_interactive_state_exp_with_one_hint_and_no_solution" +states { + key: "Text" + value { + name: "Text" + recorded_voiceovers { + key: "feedback_1" + value { + } + } + recorded_voiceovers { + key: "content" + value { + } + } + recorded_voiceovers { + key: "default_outcome" + value { + } + } + recorded_voiceovers { + key: "hint_1" + value { + } + } + content { + html: "

In which language does Oppia mean \'to learn\'?

" + content_id: "content" + } + written_translations { + key: "feedback_1" + value { + } + } + written_translations { + key: "content" + value { + } + } + written_translations { + key: "default_outcome" + value { + } + } + written_translations { + key: "hint_1" + value { + } + } + interaction { + id: "TextInput" + answer_groups { + outcome { + dest_state_name: "End" + feedback { + html: "

Correct!

" + content_id: "feedback_1" + } + } + rule_specs { + input { + key: "x" + value { + translatable_set_of_normalized_string { + content_id: "" + normalized_strings: "finnish" + } + } + } + rule_type: "Equals" + } + } + hint { + hint_content { + html: "

Hint: 'Oppia' is not English.

" + content_id: "hint_1" + } + } + default_outcome { + dest_state_name: "Text" + feedback { + html: "

Not quite. Try again (or maybe use a search engine).

" + content_id: "default_outcome" + } + } + customization_args { + key: "rows" + value { + signed_int: 1 + } + } + customization_args { + key: "placeholder" + value { + custom_schema_value { + subtitled_html { + html: "Enter a language" + content_id: "ca_placeholder_0" + } + } + } + } + } + } +} +states { + key: "End" + value { + name: "End" + recorded_voiceovers { + key: "content" + value { + } + } + content { + html: "Congratulations, you have finished!" + content_id: "content" + } + written_translations { + key: "content" + value { + } + } + interaction { + id: "EndExploration" + customization_args { + key: "recommendedExplorationIds" + value { + schema_object_list { + } + } + } + } + } +} +init_state_name: "Text" +objective: "Test exploration." +title: "Prototype exploration with one hint and no solution" +language_code: "en" diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_solution.json b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_solution.json new file mode 100644 index 00000000000..9ef0a1c1a37 --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_solution.json @@ -0,0 +1,120 @@ +{ + "exploration_id": "test_single_interactive_state_exp_with_one_hint_and_solution", + "version": 1, + "exploration": { + "init_state_name": "Text", + "states": { + "Text": { + "content": { + "content_id": "content", + "html": "

In which language does Oppia mean 'to learn'?

" + }, + "interaction": { + "id": "TextInput", + "customization_args": { + "rows": { + "value": 1.0 + }, + "placeholder": { + "value": { + "content_id": "ca_placeholder_0", + "unicode_str": "Enter a language" + } + } + }, + "answer_groups": [{ + "rule_specs": [{ + "rule_type": "Equals", + "inputs": { + "x": { + "contentId": "", + "normalizedStrSet": ["finnish"] + } + } + }], + "outcome": { + "dest": "End", + "feedback": { + "content_id": "feedback_1", + "html": "

Correct!

" + }, + "labelled_as_correct": false + } + }], + "default_outcome": { + "dest": "Text", + "feedback": { + "content_id": "default_outcome", + "html": "

Not quite. Try again (or maybe use a search engine).

" + }, + "labelled_as_correct": false + }, + "hints": [{ + "hint_content": { + "content_id": "hint_1", + "html": "

Hint: 'Oppia' is not English.

" + } + }], + "solution": { + "answer_is_exclusive": false, + "correct_answer": "Finnish", + "explanation": { + "content_id": "solution", + "html": "

'Oppia' is translated from Finnish.

" + } + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "hint_1": {}, + "solution": {} + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "hint_1": {}, + "solution": {} + } + } + }, + "End": { + "content": { + "content_id": "content", + "html": "Congratulations, you have finished!" + }, + "param_changes": [], + "interaction": { + "id": "EndExploration", + "customization_args": { + "recommendedExplorationIds": { + "value": [] + } + }, + "answer_groups": [], + "default_outcome": null, + "hints": [], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {} + } + }, + "written_translations": { + "translations_mapping": { + "content": {} + } + } + } + }, + "objective": "Test exploration.", + "language_code": "en", + "title": "Prototype exploration with one hint and a solution" + } +} diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_solution.textproto b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_solution.textproto new file mode 100644 index 00000000000..8cb51023b23 --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_one_hint_and_solution.textproto @@ -0,0 +1,159 @@ +id: "test_single_interactive_state_exp_with_one_hint_and_solution" +states { + key: "Text" + value { + name: "Text" + recorded_voiceovers { + key: "feedback_1" + value { + } + } + recorded_voiceovers { + key: "content" + value { + } + } + recorded_voiceovers { + key: "default_outcome" + value { + } + } + recorded_voiceovers { + key: "solution" + value { + } + } + recorded_voiceovers { + key: "hint_1" + value { + } + } + content { + html: "

In which language does Oppia mean \'to learn\'?

" + content_id: "content" + } + written_translations { + key: "feedback_1" + value { + } + } + written_translations { + key: "content" + value { + } + } + written_translations { + key: "default_outcome" + value { + } + } + written_translations { + key: "solution" + value { + } + } + written_translations { + key: "hint_1" + value { + } + } + interaction { + id: "TextInput" + answer_groups { + outcome { + dest_state_name: "End" + feedback { + html: "

Correct!

" + content_id: "feedback_1" + } + } + rule_specs { + input { + key: "x" + value { + translatable_set_of_normalized_string { + content_id: "" + normalized_strings: "finnish" + } + } + } + rule_type: "Equals" + } + } + solution { + interaction_id: "TextInput" + correct_answer { + correct_answer: "Finnish" + } + explanation { + html: "

'Oppia' is translated from Finnish.

" + content_id: "solution" + } + } + hint { + hint_content { + html: "

Hint: 'Oppia' is not English.

" + content_id: "hint_1" + } + } + default_outcome { + dest_state_name: "Text" + feedback { + html: "

Not quite. Try again (or maybe use a search engine).

" + content_id: "default_outcome" + } + } + customization_args { + key: "rows" + value { + signed_int: 1 + } + } + customization_args { + key: "placeholder" + value { + custom_schema_value { + subtitled_html { + html: "Enter a language" + content_id: "ca_placeholder_0" + } + } + } + } + } + } +} +states { + key: "End" + value { + name: "End" + recorded_voiceovers { + key: "content" + value { + } + } + content { + html: "Congratulations, you have finished!" + content_id: "content" + } + written_translations { + key: "content" + value { + } + } + interaction { + id: "EndExploration" + customization_args { + key: "recommendedExplorationIds" + value { + schema_object_list { + } + } + } + } + } +} +init_state_name: "Text" +objective: "Test exploration." +title: "Prototype exploration with one hint and a solution" +language_code: "en" diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_only_solution.json b/domain/src/main/assets/test_single_interactive_state_exp_with_only_solution.json new file mode 100644 index 00000000000..e5aa182f58a --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_only_solution.json @@ -0,0 +1,113 @@ +{ + "exploration_id": "test_single_interactive_state_exp_with_only_solution", + "version": 1, + "exploration": { + "init_state_name": "Text", + "states": { + "Text": { + "content": { + "content_id": "content", + "html": "

In which language does Oppia mean 'to learn'?

" + }, + "interaction": { + "id": "TextInput", + "customization_args": { + "rows": { + "value": 1.0 + }, + "placeholder": { + "value": { + "content_id": "ca_placeholder_0", + "unicode_str": "Enter a language" + } + } + }, + "answer_groups": [{ + "rule_specs": [{ + "rule_type": "Equals", + "inputs": { + "x": { + "contentId": "", + "normalizedStrSet": ["finnish"] + } + } + }], + "outcome": { + "dest": "End", + "feedback": { + "content_id": "feedback_1", + "html": "

Correct!

" + }, + "labelled_as_correct": false + } + }], + "default_outcome": { + "dest": "Text", + "feedback": { + "content_id": "default_outcome", + "html": "

Not quite. Try again (or maybe use a search engine).

" + }, + "labelled_as_correct": false + }, + "hints": [], + "solution": { + "answer_is_exclusive": false, + "correct_answer": "Finnish", + "explanation": { + "content_id": "solution", + "html": "

'Oppia' is translated from Finnish.

" + } + } + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "solution": {} + } + }, + "written_translations": { + "translations_mapping": { + "feedback_1": {}, + "content": {}, + "default_outcome": {}, + "solution": {} + } + } + }, + "End": { + "content": { + "content_id": "content", + "html": "Congratulations, you have finished!" + }, + "param_changes": [], + "interaction": { + "id": "EndExploration", + "customization_args": { + "recommendedExplorationIds": { + "value": [] + } + }, + "answer_groups": [], + "default_outcome": null, + "hints": [], + "solution": null + }, + "recorded_voiceovers": { + "voiceovers_mapping": { + "content": {} + } + }, + "written_translations": { + "translations_mapping": { + "content": {} + } + } + } + }, + "objective": "Test exploration.", + "language_code": "en", + "title": "Prototype exploration with only one solution and no hints" + } +} diff --git a/domain/src/main/assets/test_single_interactive_state_exp_with_only_solution.textproto b/domain/src/main/assets/test_single_interactive_state_exp_with_only_solution.textproto new file mode 100644 index 00000000000..87c0d655155 --- /dev/null +++ b/domain/src/main/assets/test_single_interactive_state_exp_with_only_solution.textproto @@ -0,0 +1,143 @@ +id: "test_single_interactive_state_exp_with_only_solution" +states { + key: "Text" + value { + name: "Text" + recorded_voiceovers { + key: "feedback_1" + value { + } + } + recorded_voiceovers { + key: "content" + value { + } + } + recorded_voiceovers { + key: "default_outcome" + value { + } + } + recorded_voiceovers { + key: "solution" + value { + } + } + content { + html: "

In which language does Oppia mean \'to learn\'?

" + content_id: "content" + } + written_translations { + key: "feedback_1" + value { + } + } + written_translations { + key: "content" + value { + } + } + written_translations { + key: "default_outcome" + value { + } + } + written_translations { + key: "solution" + value { + } + } + interaction { + id: "TextInput" + answer_groups { + outcome { + dest_state_name: "End" + feedback { + html: "

Correct!

" + content_id: "feedback_1" + } + } + rule_specs { + input { + key: "x" + value { + translatable_set_of_normalized_string { + content_id: "" + normalized_strings: "finnish" + } + } + } + rule_type: "Equals" + } + } + solution { + interaction_id: "TextInput" + correct_answer { + correct_answer: "Finnish" + } + explanation { + html: "

'Oppia' is translated from Finnish.

" + content_id: "solution" + } + } + default_outcome { + dest_state_name: "Text" + feedback { + html: "

Not quite. Try again (or maybe use a search engine).

" + content_id: "default_outcome" + } + } + customization_args { + key: "rows" + value { + signed_int: 1 + } + } + customization_args { + key: "placeholder" + value { + custom_schema_value { + subtitled_html { + html: "Enter a language" + content_id: "ca_placeholder_0" + } + } + } + } + } + } +} +states { + key: "End" + value { + name: "End" + recorded_voiceovers { + key: "content" + value { + } + } + content { + html: "Congratulations, you have finished!" + content_id: "content" + } + written_translations { + key: "content" + value { + } + } + interaction { + id: "EndExploration" + customization_args { + key: "recommendedExplorationIds" + value { + schema_object_list { + } + } + } + } + } +} +init_state_name: "Text" +objective: "Test exploration." +title: "Prototype exploration with only one solution and no hints" +language_code: "en" diff --git a/domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt b/domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt index 459af038a6d..3bf4c16bd62 100644 --- a/domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt +++ b/domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt @@ -7,13 +7,12 @@ import org.oppia.android.app.model.CheckpointState import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.Exploration import org.oppia.android.app.model.ExplorationCheckpoint -import org.oppia.android.app.model.Hint +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.model.Solution -import org.oppia.android.app.model.State import org.oppia.android.app.model.UserAnswer import org.oppia.android.domain.classify.AnswerClassificationController import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationCheckpointController +import org.oppia.android.domain.hintsandsolution.HintHandler import org.oppia.android.domain.oppialogger.OppiaLogger import org.oppia.android.domain.oppialogger.exceptions.ExceptionsController import org.oppia.android.domain.topic.StoryProgressController @@ -48,8 +47,9 @@ class ExplorationProgressController @Inject constructor( private val explorationCheckpointController: ExplorationCheckpointController, private val storyProgressController: StoryProgressController, private val oppiaClock: OppiaClock, - private val oppiaLogger: OppiaLogger -) { + private val oppiaLogger: OppiaLogger, + private val hintHandlerFactory: HintHandler.Factory +) : HintHandler.HintMonitor { // TODO(#179): Add support for parameters. // TODO(#3622): Update the internal locking of this controller to use something like an in-memory // blocking cache to simplify state locking. However, doing this correctly requires a fix in @@ -70,6 +70,7 @@ class ExplorationProgressController @Inject constructor( ) private val explorationProgress = ExplorationProgress() private val explorationProgressLock = ReentrantLock() + private lateinit var hintHandler: HintHandler /** Resets this controller to begin playing the specified [Exploration]. */ internal fun beginExplorationAsync( @@ -92,6 +93,7 @@ class ExplorationProgressController @Inject constructor( this.shouldSavePartialProgress = shouldSavePartialProgress checkpointState = CheckpointState.CHECKPOINT_UNSAVED } + hintHandler = hintHandlerFactory.create(this) explorationProgress.advancePlayStageTo(ExplorationProgress.PlayStage.LOADING_EXPLORATION) asyncDataSubscriptionManager.notifyChangeAsync(CURRENT_STATE_DATA_PROVIDER_ID) } @@ -107,6 +109,13 @@ class ExplorationProgressController @Inject constructor( } } + override fun onHelpIndexChanged() { + explorationProgressLock.withLock { + saveExplorationCheckpoint() + } + asyncDataSubscriptionManager.notifyChangeAsync(CURRENT_STATE_DATA_PROVIDER_ID) + } + /** * Submits an answer to the current state and returns how the UI should respond to this answer. * The returned [LiveData] will only have at most two results posted: a pending result, and then a @@ -174,17 +183,26 @@ class ExplorationProgressController @Inject constructor( answerOutcome = explorationProgress.stateGraph.computeAnswerOutcomeForResult(topPendingState, outcome) explorationProgress.stateDeck.submitAnswer(userAnswer, answerOutcome.feedback) + // Follow the answer's outcome to another part of the graph if it's different. - if (answerOutcome.destinationCase == AnswerOutcome.DestinationCase.STATE_NAME) { - explorationProgress.stateDeck.pushState( - explorationProgress.stateGraph.getState(answerOutcome.stateName), - prohibitSameStateName = true - ) + val ephemeralState = computeCurrentEphemeralState() + when { + answerOutcome.destinationCase == AnswerOutcome.DestinationCase.STATE_NAME -> { + val newState = explorationProgress.stateGraph.getState(answerOutcome.stateName) + explorationProgress.stateDeck.pushState(newState, prohibitSameStateName = true) + hintHandler.finishState(newState) + } + ephemeralState.stateTypeCase == EphemeralState.StateTypeCase.PENDING_STATE -> { + // Schedule, or show immediately, a new hint or solution based on the current + // ephemeral state of the exploration because a new wrong answer was submitted. + hintHandler.handleWrongAnswerSubmission(ephemeralState.pendingState.wrongAnswerCount) + } } } finally { - // If the answer was submitted on behalf of the Continue interaction, don't save - // checkpoint because it will be saved when the learner moves to the next state. if (!doesInteractionAutoContinue(answerOutcome.state.interaction.id)) { + // If the answer was not submitted on behalf of the Continue interaction, update the + // hint state and save checkpoint because it will be saved when the learner moves to the + // next state. saveExplorationCheckpoint() } @@ -204,11 +222,15 @@ class ExplorationProgressController @Inject constructor( } } - fun submitHintIsRevealed( - state: State, - hintIsRevealed: Boolean, - hintIndex: Int - ): LiveData> { + /** + * Notifies the controller that the user wishes to reveal a hint. + * + * @param hintIndex index of the hint that was revealed in the hint list of the current pending + * state + * @return a one-time [LiveData] that indicates success/failure of the operation (the actual + * payload of the result isn't relevant) + */ + fun submitHintIsRevealed(hintIndex: Int): LiveData> { try { explorationProgressLock.withLock { check( @@ -229,25 +251,16 @@ class ExplorationProgressController @Inject constructor( ) { "Cannot submit an answer while another answer is pending." } - lateinit var hint: Hint try { - explorationProgress.stateDeck.submitHintRevealed(state, hintIsRevealed, hintIndex) - hint = explorationProgress.stateGraph.computeHintForResult( - state, - hintIsRevealed, - hintIndex - ) - explorationProgress.stateDeck.pushStateForHint(state, hintIndex) + hintHandler.viewHint(hintIndex) } finally { - // Mark a checkpoint in the exploration everytime a new hint is revealed. - saveExplorationCheckpoint() // Ensure that the user always returns to the VIEWING_STATE stage to avoid getting stuck // in an 'always showing hint' situation. This can specifically happen if hint throws an // exception. explorationProgress.advancePlayStageTo(ExplorationProgress.PlayStage.VIEWING_STATE) } asyncDataSubscriptionManager.notifyChangeAsync(CURRENT_STATE_DATA_PROVIDER_ID) - return MutableLiveData(AsyncResult.success(hint)) + return MutableLiveData(AsyncResult.success(null)) } } catch (e: Exception) { exceptionsController.logNonFatalException(e) @@ -255,9 +268,13 @@ class ExplorationProgressController @Inject constructor( } } - fun submitSolutionIsRevealed( - state: State - ): LiveData> { + /** + * Notifies the controller that the user has revealed the solution to the current state. + * + * @return a one-time [LiveData] that indicates success/failure of the operation (the actual + * payload of the result isn't relevant) + */ + fun submitSolutionIsRevealed(): LiveData> { try { explorationProgressLock.withLock { check( @@ -278,15 +295,9 @@ class ExplorationProgressController @Inject constructor( ) { "Cannot submit an answer while another answer is pending." } - lateinit var solution: Solution try { - - explorationProgress.stateDeck.submitSolutionRevealed(state) - solution = explorationProgress.stateGraph.computeSolutionForResult(state) - explorationProgress.stateDeck.pushStateForSolution(state) + hintHandler.viewSolution() } finally { - // Mark a checkpoint in the exploration if the solution is revealed. - saveExplorationCheckpoint() // Ensure that the user always returns to the VIEWING_STATE stage to avoid getting stuck // in an 'always showing solution' situation. This can specifically happen if solution // throws an exception. @@ -294,7 +305,7 @@ class ExplorationProgressController @Inject constructor( } asyncDataSubscriptionManager.notifyChangeAsync(CURRENT_STATE_DATA_PROVIDER_ID) - return MutableLiveData(AsyncResult.success(solution)) + return MutableLiveData(AsyncResult.success(null)) } } catch (e: Exception) { exceptionsController.logNonFatalException(e) @@ -334,10 +345,11 @@ class ExplorationProgressController @Inject constructor( ) { "Cannot navigate to a previous state if an answer submission is pending." } + hintHandler.navigateToPreviousState() explorationProgress.stateDeck.navigateToPreviousState() asyncDataSubscriptionManager.notifyChangeAsync(CURRENT_STATE_DATA_PROVIDER_ID) } - return MutableLiveData(AsyncResult.success(null)) + return MutableLiveData(AsyncResult.success(null)) } catch (e: Exception) { exceptionsController.logNonFatalException(e) return MutableLiveData(AsyncResult.failed(e)) @@ -359,7 +371,6 @@ class ExplorationProgressController @Inject constructor( * listen to this result for failures, and instead rely on [getCurrentState] for observing a * successful transition to another state. */ - fun moveToNextState(): LiveData> { try { explorationProgressLock.withLock { @@ -383,20 +394,127 @@ class ExplorationProgressController @Inject constructor( } explorationProgress.stateDeck.navigateToNextState() - // Only mark checkpoint if current state is pending state. This ensures that checkpoints - // will not be marked on any of the completed states. if (explorationProgress.stateDeck.isCurrentStateTopOfDeck()) { + hintHandler.navigateBackToLatestPendingState() + + // Only mark checkpoint if current state is pending state. This ensures that checkpoints + // will not be marked on any of the completed states. saveExplorationCheckpoint() } asyncDataSubscriptionManager.notifyChangeAsync(CURRENT_STATE_DATA_PROVIDER_ID) } - return MutableLiveData(AsyncResult.success(null)) + return MutableLiveData(AsyncResult.success(null)) } catch (e: Exception) { exceptionsController.logNonFatalException(e) return MutableLiveData(AsyncResult.failed(e)) } } + /** + * Returns a [DataProvider] monitoring the current [EphemeralState] the learner is currently + * viewing. If this state corresponds to a a terminal state, then the learner has completed the + * exploration. Note that [moveToPreviousState] and [moveToNextState] will automatically update + * observers of this data provider when the next state is navigated to. + * + * This [DataProvider] may initially be pending while the exploration object is loaded. It may + * also switch from a completed to a pending result during transient operations like submitting an + * answer via [submitAnswer]. Calling code should be made resilient to this by caching the current + * state object to display since it may disappear temporarily during answer submission. Calling + * code should persist this state object across configuration changes if needed since it cannot + * rely on this [DataProvider] for immediate state reconstitution after configuration changes. + * + * The underlying state returned by this function can only be changed by calls to + * [moveToNextState] and [moveToPreviousState], or the exploration data controller if another + * exploration is loaded. UI code can be confident only calls from the UI layer will trigger state + * changes here to ensure atomicity between receiving and making state changes. + * + * This method is safe to be called before an exploration has started. If there is no ongoing + * exploration, it should return a pending state. + */ + fun getCurrentState(): DataProvider = currentStateDataProvider + + private suspend fun retrieveCurrentStateAsync(): AsyncResult { + return try { + retrieveCurrentStateWithinCacheAsync() + } catch (e: Exception) { + exceptionsController.logNonFatalException(e) + AsyncResult.failed(e) + } + } + + @Suppress("RedundantSuspendModifier") // Function is 'suspend' to restrict calling some methods. + private suspend fun retrieveCurrentStateWithinCacheAsync(): AsyncResult { + val explorationId: String? = explorationProgressLock.withLock { + if (explorationProgress.playStage == ExplorationProgress.PlayStage.LOADING_EXPLORATION) { + explorationProgress.currentExplorationId + } else null + } + + val exploration = explorationId?.let(explorationRetriever::loadExploration) + + explorationProgressLock.withLock { + // It's possible for the exploration ID or stage to change between critical sections. However, + // this is the only way to ensure the exploration is loaded since suspended functions cannot + // be called within a mutex. Note that it's also possible for the stage to change between + // critical sections, sometimes due to this suspend function being called multiple times and a + // former call finishing the exploration load. + check( + exploration == null || + explorationProgress.currentExplorationId == explorationId + ) { + "Encountered race condition when retrieving exploration. ID changed from $explorationId" + + " to ${explorationProgress.currentExplorationId}" + } + return when (explorationProgress.playStage) { + ExplorationProgress.PlayStage.NOT_PLAYING -> AsyncResult.pending() + ExplorationProgress.PlayStage.LOADING_EXPLORATION -> { + try { + // The exploration must be available for this stage since it was loaded above. + finishLoadExploration(exploration!!, explorationProgress) + AsyncResult.success( + computeCurrentEphemeralState() + .toBuilder() + .setCheckpointState(explorationProgress.checkpointState) + .build() + ) + } catch (e: Exception) { + exceptionsController.logNonFatalException(e) + AsyncResult.failed(e) + } + } + ExplorationProgress.PlayStage.VIEWING_STATE -> + AsyncResult.success( + computeCurrentEphemeralState() + .toBuilder() + .setCheckpointState(explorationProgress.checkpointState) + .build() + ) + ExplorationProgress.PlayStage.SUBMITTING_ANSWER -> AsyncResult.pending() + } + } + } + + private fun finishLoadExploration(exploration: Exploration, progress: ExplorationProgress) { + // The exploration must be initialized first since other lazy fields depend on it being inited. + progress.currentExploration = exploration + progress.stateGraph.reset(exploration.statesMap) + progress.stateDeck.resetDeck(progress.stateGraph.getState(exploration.initStateName)) + + // Advance the stage, but do not notify observers since the current state can be reported + // immediately to the UI. + progress.advancePlayStageTo(ExplorationProgress.PlayStage.VIEWING_STATE) + + hintHandler.startWatchingForHintsInNewState(progress.stateDeck.getCurrentState()) + + // Mark a checkpoint in the exploration once the exploration has loaded. + saveExplorationCheckpoint() + } + + private fun computeCurrentEphemeralState(): EphemeralState = + explorationProgress.stateDeck.getCurrentEphemeralState(computeCurrentHelpIndex()) + + private fun computeCurrentHelpIndex(): HelpIndex = hintHandler.getCurrentHelpIndex() + /** * Checks if checkpointing is enabled, if checkpointing is enabled this function creates a * checkpoint with the latest progress and saves it using [ExplorationCheckpointController]. @@ -418,7 +536,8 @@ class ExplorationProgressController @Inject constructor( explorationProgress.stateDeck.createExplorationCheckpoint( explorationProgress.currentExploration.version, explorationProgress.currentExploration.title, - oppiaClock.getCurrentTimeMs() + oppiaClock.getCurrentTimeMs(), + computeCurrentHelpIndex() ) val deferred = explorationCheckpointController.recordExplorationCheckpointAsync( @@ -506,103 +625,6 @@ class ExplorationProgressController @Inject constructor( } } - /** - * Returns a [DataProvider] monitoring the current [EphemeralState] the learner is currently - * viewing. If this state corresponds to a a terminal state, then the learner has completed the - * exploration. Note that [moveToPreviousState] and [moveToNextState] will automatically update - * observers of this data provider when the next state is navigated to. - * - * This [DataProvider] may initially be pending while the exploration object is loaded. It may - * also switch from a completed to a pending result during transient operations like submitting an - * answer via [submitAnswer]. Calling code should be made resilient to this by caching the current - * state object to display since it may disappear temporarily during answer submission. Calling - * code should persist this state object across configuration changes if needed since it cannot - * rely on this [DataProvider] for immediate state reconstitution after configuration changes. - * - * The underlying state returned by this function can only be changed by calls to - * [moveToNextState] and [moveToPreviousState], or the exploration data controller if another - * exploration is loaded. UI code can be confident only calls from the UI layer will trigger state - * changes here to ensure atomicity between receiving and making state changes. - * - * This method is safe to be called before an exploration has started. If there is no ongoing - * exploration, it should return a pending state. - */ - fun getCurrentState(): DataProvider = currentStateDataProvider - - private suspend fun retrieveCurrentStateAsync(): AsyncResult { - return try { - retrieveCurrentStateWithinCacheAsync() - } catch (e: Exception) { - exceptionsController.logNonFatalException(e) - AsyncResult.failed(e) - } - } - - private suspend fun retrieveCurrentStateWithinCacheAsync(): AsyncResult { - val explorationId: String? = explorationProgressLock.withLock { - if (explorationProgress.playStage == ExplorationProgress.PlayStage.LOADING_EXPLORATION) { - explorationProgress.currentExplorationId - } else null - } - - val exploration = explorationId?.let(explorationRetriever::loadExploration) - - explorationProgressLock.withLock { - // It's possible for the exploration ID or stage to change between critical sections. However, - // this is the only way to ensure the exploration is loaded since suspended functions cannot - // be called within a mutex. Note that it's also possible for the stage to change between - // critical sections, sometimes due to this suspend function being called multiple times and a - // former call finishing the exploration load. - check( - exploration == null || - explorationProgress.currentExplorationId == explorationId - ) { - "Encountered race condition when retrieving exploration. ID changed from $explorationId" + - " to ${explorationProgress.currentExplorationId}" - } - return when (explorationProgress.playStage) { - ExplorationProgress.PlayStage.NOT_PLAYING -> AsyncResult.pending() - ExplorationProgress.PlayStage.LOADING_EXPLORATION -> { - try { - // The exploration must be available for this stage since it was loaded above. - finishLoadExploration(exploration!!, explorationProgress) - AsyncResult.success( - explorationProgress.stateDeck.getCurrentEphemeralState() - .toBuilder() - .setCheckpointState(explorationProgress.checkpointState) - .build() - ) - } catch (e: Exception) { - exceptionsController.logNonFatalException(e) - AsyncResult.failed(e) - } - } - ExplorationProgress.PlayStage.VIEWING_STATE -> - AsyncResult.success( - explorationProgress.stateDeck.getCurrentEphemeralState() - .toBuilder() - .setCheckpointState(explorationProgress.checkpointState) - .build() - ) - ExplorationProgress.PlayStage.SUBMITTING_ANSWER -> AsyncResult.pending() - } - } - } - - private fun finishLoadExploration(exploration: Exploration, progress: ExplorationProgress) { - // The exploration must be initialized first since other lazy fields depend on it being inited. - progress.currentExploration = exploration - progress.stateGraph.reset(exploration.statesMap) - progress.stateDeck.resetDeck(progress.stateGraph.getState(exploration.initStateName)) - - // Advance the stage, but do not notify observers since the current state can be reported - // immediately to the UI. - progress.advancePlayStageTo(ExplorationProgress.PlayStage.VIEWING_STATE) - - // Mark a checkpoint in the exploration once the exploration has loaded. - saveExplorationCheckpoint() - } - /** * Returns whether the specified interaction automatically continues the user to the next state * upon completion. diff --git a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt similarity index 83% rename from app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt rename to domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt index 223996ceb99..2afe7621d6c 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt @@ -1,4 +1,4 @@ -package org.oppia.android.app.player.state.hintsandsolution +package org.oppia.android.domain.hintsandsolution import javax.inject.Qualifier diff --git a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsMillis.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsMillis.kt similarity index 81% rename from app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsMillis.kt rename to domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsMillis.kt index 600c354db98..371a2bb8f81 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsMillis.kt +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsMillis.kt @@ -1,4 +1,4 @@ -package org.oppia.android.app.player.state.hintsandsolution +package org.oppia.android.domain.hintsandsolution import javax.inject.Qualifier diff --git a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowInitialHintMillis.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowInitialHintMillis.kt similarity index 78% rename from app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowInitialHintMillis.kt rename to domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowInitialHintMillis.kt index f02d8c74d9b..5abba359af7 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowInitialHintMillis.kt +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowInitialHintMillis.kt @@ -1,5 +1,4 @@ -package org.oppia.android.app.player.state.hintsandsolution - +package org.oppia.android.domain.hintsandsolution import javax.inject.Qualifier /** diff --git a/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HelpIndexExtensions.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HelpIndexExtensions.kt new file mode 100644 index 00000000000..f2339f68673 --- /dev/null +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HelpIndexExtensions.kt @@ -0,0 +1,28 @@ +package org.oppia.android.domain.hintsandsolution + +import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.EVERYTHING_REVEALED +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.INDEXTYPE_NOT_SET +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.LATEST_REVEALED_HINT_INDEX +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.SHOW_SOLUTION +import org.oppia.android.app.model.Hint + +/** + * Returns whether the specified [hintIndex] relative to the proivded list of [Hint]s has been seen + * by the user based on this [HelpIndex]. + */ +fun HelpIndex.isHintRevealed(hintIndex: Int, hintList: List): Boolean { + val lastShownHintIndex = when (indexTypeCase) { + SHOW_SOLUTION, EVERYTHING_REVEALED -> hintList.lastIndex + NEXT_AVAILABLE_HINT_INDEX -> nextAvailableHintIndex - 1 + LATEST_REVEALED_HINT_INDEX -> latestRevealedHintIndex + INDEXTYPE_NOT_SET, null -> -1 + } + return hintIndex <= lastShownHintIndex +} + +/** + * Returns whether, based on a specified [HelpIndex], the solution has been viewed by the learner. + */ +fun HelpIndex.isSolutionRevealed(): Boolean = indexTypeCase == EVERYTHING_REVEALED diff --git a/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandler.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandler.kt new file mode 100644 index 00000000000..5fdc8c22716 --- /dev/null +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandler.kt @@ -0,0 +1,93 @@ +package org.oppia.android.domain.hintsandsolution + +import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.State + +/** + * Handler for showing hints to the learner after a period of time in the event they submit a + * wrong answer. + * + * Note that the exact behavior of when a hint or solution is made available is up to the + * implementation, but it's assumed that: + * 1. This class is the sole decision maker for whether a hint is available or revealed (and ditto + * for solutions) + * 2. Hints must be viewed in order + * 3. Later hints are not available until all previous hints have been revealed + * 4. The solution cannot be revealed until all previous hints have been revealed + * + * Implementations of this class are safe to access across multiple threads, but care must be taken + * when calling back into this class from [HintMonitor] since that could cause deadlocks. Note also + * that this class may block the calling thread. While the operations this class performs + * synchronously should be quick, care should be taken about heavy usage of this class on the main + * thread as it may introduce janky behavior. + */ +interface HintHandler { + + /** + * Starts watching for potential hints to be shown (e.g. if a user doesn't submit an answer after + * a certain amount of time). This is meant to only be called once at the beginning of a state. + */ + fun startWatchingForHintsInNewState(state: State) + + /** + * Indicates that the current state has ended and a new one should start being monitored. This + * will cancel any previously pending background operations and potentially starts new ones + * corresponding to the new state. + */ + fun finishState(newState: State) + + /** + * Notifies the handler that a wrong answer was submitted. + * + * @param wrongAnswerCount the total number of wrong answers submitted to date + */ + fun handleWrongAnswerSubmission(wrongAnswerCount: Int) + + /** Notifies the handler that the user revealed a hint corresponding to the specified index. */ + fun viewHint(hintIndex: Int) + + /** Notifies the handler that the user revealed the the solution for the current state. */ + fun viewSolution() + + /** + * Notifies the handler that the user navigated to a previously completed state. This will + * potentially cancel any ongoing operations to avoid the hint counter continuing when navigating + * an earlier state. + */ + fun navigateToPreviousState() + + /** + * Notifies the handler that the user has navigated back to the latest (pending) state. Note that + * this may resume background operations, but it does not guarantee that those start at the same + * time that they left off at (counters may be reset upon returning to the latest state). + */ + fun navigateBackToLatestPendingState() + + /** Returns the [HelpIndex] corresponding to the current pending state. */ + fun getCurrentHelpIndex(): HelpIndex + + /** A callback interface for monitoring changes to [HintHandler]. */ + interface HintMonitor { + /** + * Called when the [HelpIndex] managed by the [HintHandler] has changed. To get the latest + * state, call [HintHandler.getCurrentHelpIndex]. Note that this method may be called on a + * background thread. + */ + fun onHelpIndexChanged() + } + + /** + * Factory for creating new [HintHandler]s. + * + * Note that instances of this class are injectable in the application component. + */ + interface Factory { + /** + * Creates a new [HintHandler]. + * + * @param hintMonitor a [HintMonitor] to observe async changes to hints/solution + * @return a new [HintHandler] for managing hint/solution state for a specific play session + */ + fun create(hintMonitor: HintMonitor): HintHandler + } +} diff --git a/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerImpl.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerImpl.kt new file mode 100644 index 00000000000..6e8f972b69b --- /dev/null +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerImpl.kt @@ -0,0 +1,339 @@ +package org.oppia.android.domain.hintsandsolution + +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.INDEXTYPE_NOT_SET +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX +import org.oppia.android.app.model.HelpIndex.IndexTypeCase.SHOW_SOLUTION +import org.oppia.android.app.model.State +import org.oppia.android.util.threading.BackgroundDispatcher +import java.util.concurrent.locks.ReentrantLock +import javax.inject.Inject +import kotlin.concurrent.withLock + +/** + * Production implementation of [HintHandler] that implements hints & solutions in parity with the + * Oppia web platform. + * + * # Flow chart for when hints are shown + * + * Submit 1st Submit wrong + * wrong answer answer + * +---+ +---+ + * | | | | + * | v | v + * +-+---+----+ +-+---+-----+ +----------+ + * Initial| No | Wait 60s | | View hint | Hint | + * state | hint +----------->+ Hint +---------->+ consumed | + * +----->+ released | or, submit | available | Wait 30s | | + * | | 2nd wrong | +<----------+ | + * +----------+ answer +----+------+ +----+-----+ + * ^ | + * |Wait 10s | + * | | + * +----+------+ | + * +--->+ No | Submit wrong | + * Submit wrong| | hint | answer | + * answer | | available +<---------------+ + * +----+ | + * +-----------+ + * + * # Logic for selecting a hint + * + * Hints are selected based on the availability of hints to show, and any previous hints that have + * been shown. A new hint will only be made available if its previous hint has been viewed by the + * learner. Hints are always shown in order. If all hints have been exhausted and viewed by the + * user, then the 'hint available' state in the diagram above will trigger the solution to be + * made available to view, if a solution is present. Once the solution is viewed by the learner, + * they will reach a terminal state for hints and no additional hints or solutions will be made + * available. + */ +class HintHandlerImpl private constructor( + private val delayShowInitialHintMs: Long, + private val delayShowAdditionalHintsMs: Long, + private val delayShowAdditionalHintsFromWrongAnswerMs: Long, + backgroundCoroutineDispatcher: CoroutineDispatcher, + private val hintMonitor: HintHandler.HintMonitor +) : HintHandler { + private val handlerLock = ReentrantLock() + private val backgroundCoroutineScope = CoroutineScope(backgroundCoroutineDispatcher) + + private var trackedWrongAnswerCount = 0 + private lateinit var pendingState: State + private var hintSequenceNumber = 0 + private var lastRevealedHintIndex = -1 + private var latestAvailableHintIndex = -1 + private var solutionIsAvailable = false + private var solutionIsRevealed = false + + override fun startWatchingForHintsInNewState(state: State) { + handlerLock.withLock { + pendingState = state + hintMonitor.onHelpIndexChanged() + maybeScheduleShowHint(wrongAnswerCount = 0) + } + } + + override fun finishState(newState: State) { + handlerLock.withLock { + reset() + startWatchingForHintsInNewState(newState) + } + } + + override fun handleWrongAnswerSubmission(wrongAnswerCount: Int) { + handlerLock.withLock { + maybeScheduleShowHint(wrongAnswerCount) + } + } + + override fun viewHint(hintIndex: Int) { + handlerLock.withLock { + val helpIndex = computeCurrentHelpIndex() + check( + helpIndex.indexTypeCase == NEXT_AVAILABLE_HINT_INDEX && + helpIndex.nextAvailableHintIndex == hintIndex + ) { + "Cannot reveal hint for current index: ${helpIndex.indexTypeCase} (trying to reveal hint:" + + " $hintIndex)" + } + + cancelPendingTasks() + lastRevealedHintIndex = lastRevealedHintIndex.coerceAtLeast(hintIndex) + hintMonitor.onHelpIndexChanged() + maybeScheduleShowHint() + } + } + + override fun viewSolution() { + handlerLock.withLock { + val helpIndex = computeCurrentHelpIndex() + check(helpIndex.indexTypeCase == SHOW_SOLUTION) { + "Cannot reveal solution for current index: ${helpIndex.indexTypeCase}" + } + + cancelPendingTasks() + solutionIsRevealed = true + hintMonitor.onHelpIndexChanged() + } + } + + override fun navigateToPreviousState() { + // Cancel tasks from the top pending state to avoid hint counters continuing after navigating + // away. + handlerLock.withLock { + cancelPendingTasks() + } + } + + override fun navigateBackToLatestPendingState() { + handlerLock.withLock { + maybeScheduleShowHint() + } + } + + override fun getCurrentHelpIndex(): HelpIndex = handlerLock.withLock { + computeCurrentHelpIndex() + } + + private fun cancelPendingTasks() { + // Cancel any potential pending hints by advancing the sequence number. Note that this isn't + // reset to 0 to ensure that all previous hint tasks are cancelled, and new tasks can be + // scheduled without overlapping with past sequence numbers. + hintSequenceNumber++ + } + + private fun maybeScheduleShowHint(wrongAnswerCount: Int = trackedWrongAnswerCount) { + if (!pendingState.offersHelp()) { + // If this state has no help to show, do nothing. + return + } + + // Start showing hints after a wrong answer is submitted or if the user appears stuck (e.g. + // doesn't answer after some duration). Note that if there's already a timer to show a hint, + // it will be reset for each subsequent answer. + val currentHelpIndex = computeCurrentHelpIndex() + val nextUnrevealedHelpIndex = getNextHelpIndexToReveal() + val isFirstHint = currentHelpIndex.indexTypeCase == INDEXTYPE_NOT_SET + if (wrongAnswerCount == trackedWrongAnswerCount) { + // If no answers have been submitted, schedule a task to automatically help after a fixed + // amount of time. This will automatically reset if something changes other than answers + // (e.g. revealing a hint), which may trigger more help to become available. + if (isFirstHint) { + // The learner needs to wait longer for the initial hint to show since they need some time + // to read through and consider the question. + scheduleShowHint(delayShowInitialHintMs, nextUnrevealedHelpIndex) + } else { + scheduleShowHint(delayShowAdditionalHintsMs, nextUnrevealedHelpIndex) + } + } else { + // See if the learner's new wrong answer justifies showing a hint. + if (isFirstHint) { + if (wrongAnswerCount > 1) { + // If more than one answer has been submitted and no hint has yet been shown, show a + // hint immediately since the learner is probably stuck. + showHintImmediately(nextUnrevealedHelpIndex) + } + } else { + // Otherwise, always schedule to show a hint on a new wrong answer for subsequent hints. + scheduleShowHint( + delayShowAdditionalHintsFromWrongAnswerMs, + nextUnrevealedHelpIndex + ) + } + trackedWrongAnswerCount = wrongAnswerCount + } + } + + /** Resets this handler to prepare it for a new state, cancelling any pending hints. */ + private fun reset() { + trackedWrongAnswerCount = 0 + // Cancel tasks rather than resetting to avoid potential cases where previous tasks can carry to + // the next state. + cancelPendingTasks() + lastRevealedHintIndex = -1 + latestAvailableHintIndex = -1 + solutionIsAvailable = false + solutionIsRevealed = false + } + + private fun computeCurrentHelpIndex(): HelpIndex { + val hintList = pendingState.interaction.hintList + val hasSolution = pendingState.hasSolution() + val hasAtLeastOneHintAvailable = latestAvailableHintIndex != -1 + val hasSeenAllAvailableHints = latestAvailableHintIndex == lastRevealedHintIndex + val hasSeenAllHints = lastRevealedHintIndex == hintList.lastIndex + val hasViewableSolution = hasSolution && solutionIsAvailable + + return when { + // No hints or solution are available to be shown. + !pendingState.offersHelp() -> HelpIndex.getDefaultInstance() + + // The solution has been revealed. + solutionIsRevealed -> HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + + // All hints have been shown and a solution can be shown. + hasSeenAllHints && hasViewableSolution -> HelpIndex.newBuilder().apply { + showSolution = true + }.build() + + // All hints have been shown & there is no solution. + hasSeenAllHints && !hasSolution -> HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + + // Hints are available (though they may have already been seen). + hasAtLeastOneHintAvailable -> + if (hasSeenAllAvailableHints) { + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = lastRevealedHintIndex + }.build() + } else { + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = latestAvailableHintIndex + }.build() + } + + // No hints are available to be shown yet. + else -> HelpIndex.getDefaultInstance() + } + } + + /** + * Returns the [HelpIndex] of the next hint or solution that hasn't yet been revealed, or + * default if there is none. + */ + private fun getNextHelpIndexToReveal(): HelpIndex { + // Return the index of the first unrevealed hint, or the length of the list if all have been + // revealed. + val hintList = pendingState.interaction.hintList + val solution = pendingState.interaction.solution + + val hasHints = hintList.isNotEmpty() + val hasHelp = hasHints || solution.hasCorrectAnswer() + val lastUnrevealedHintIndex = lastRevealedHintIndex + 1 + + return if (!hasHelp) { + HelpIndex.getDefaultInstance() + } else if (hasHints && lastUnrevealedHintIndex < hintList.size) { + HelpIndex.newBuilder().setNextAvailableHintIndex(lastUnrevealedHintIndex).build() + } else if (solution.hasCorrectAnswer() && !solutionIsRevealed) { + HelpIndex.newBuilder().setShowSolution(true).build() + } else { + HelpIndex.newBuilder().setEverythingRevealed(true).build() + } + } + + /** + * Schedules to allow the hint of the specified index to be shown after the specified delay, + * cancelling any previously pending hints initiated by calls to this method. + */ + private fun scheduleShowHint(delayMs: Long, helpIndexToShow: HelpIndex) { + val targetSequenceNumber = ++hintSequenceNumber + backgroundCoroutineScope.launch { + delay(delayMs) + handlerLock.withLock { + showHint(targetSequenceNumber, helpIndexToShow) + } + } + } + + /** + * Immediately indicates the specified hint is ready to be shown, cancelling any previously + * pending hints initiated by calls to [scheduleShowHint]. + */ + private fun showHintImmediately(helpIndexToShow: HelpIndex) { + showHint(++hintSequenceNumber, helpIndexToShow) + } + + private fun showHint(targetSequenceNumber: Int, nextHelpIndexToShow: HelpIndex) { + // Only finish this timer if no other hints were scheduled and no cancellations occurred. + if (targetSequenceNumber == hintSequenceNumber) { + val previousHelpIndex = computeCurrentHelpIndex() + + when (nextHelpIndexToShow.indexTypeCase) { + NEXT_AVAILABLE_HINT_INDEX -> { + latestAvailableHintIndex = nextHelpIndexToShow.nextAvailableHintIndex + } + SHOW_SOLUTION -> solutionIsAvailable = true + else -> {} // Nothing else to do. + } + + // Only indicate the hint is available if its index is actually new (including if it + // becomes null such as in the case of the solution becoming available). + if (nextHelpIndexToShow != previousHelpIndex) { + hintMonitor.onHelpIndexChanged() + } + } + } + + /** Implementation of [HintHandler.Factory]. */ + class FactoryImpl @Inject constructor( + @DelayShowInitialHintMillis private val delayShowInitialHintMs: Long, + @DelayShowAdditionalHintsMillis private val delayShowAdditionalHintsMs: Long, + @DelayShowAdditionalHintsFromWrongAnswerMillis + private val delayShowAdditionalHintsFromWrongAnswerMs: Long, + @BackgroundDispatcher private val backgroundCoroutineDispatcher: CoroutineDispatcher + ) : HintHandler.Factory { + override fun create(hintMonitor: HintHandler.HintMonitor): HintHandler { + return HintHandlerImpl( + delayShowInitialHintMs, + delayShowAdditionalHintsMs, + delayShowAdditionalHintsFromWrongAnswerMs, + backgroundCoroutineDispatcher, + hintMonitor + ) + } + } +} + +/** Returns whether this state has a solution to show. */ +private fun State.hasSolution(): Boolean = interaction.solution.hasCorrectAnswer() + +/** Returns whether this state has help that the user can see. */ +private fun State.offersHelp(): Boolean = interaction.hintList.isNotEmpty() || hasSolution() diff --git a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt similarity index 90% rename from app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt rename to domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt index b0c431c64f4..dd2709ed56b 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt @@ -1,4 +1,4 @@ -package org.oppia.android.app.player.state.hintsandsolution +package org.oppia.android.domain.hintsandsolution import dagger.Module import dagger.Provides diff --git a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigModule.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigModule.kt similarity index 91% rename from app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigModule.kt rename to domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigModule.kt index 24cde21f077..aead25b5804 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigModule.kt +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigModule.kt @@ -1,4 +1,4 @@ -package org.oppia.android.app.player.state.hintsandsolution +package org.oppia.android.domain.hintsandsolution import dagger.Module import dagger.Provides diff --git a/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModule.kt b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModule.kt new file mode 100644 index 00000000000..85dffd7dd96 --- /dev/null +++ b/domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModule.kt @@ -0,0 +1,11 @@ +package org.oppia.android.domain.hintsandsolution + +import dagger.Binds +import dagger.Module + +/** Production module for providing hints & solution related dependencies. */ +@Module +interface HintsAndSolutionProdModule { + @Binds + fun provideHintHandlerFactoryImpl(impl: HintHandlerImpl.FactoryImpl): HintHandler.Factory +} diff --git a/domain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt b/domain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt index 57dcb1fa7e8..82ecc532d4d 100644 --- a/domain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt +++ b/domain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt @@ -4,14 +4,14 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import org.oppia.android.app.model.AnsweredQuestionOutcome import org.oppia.android.app.model.EphemeralQuestion -import org.oppia.android.app.model.Hint +import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.Question -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.State import org.oppia.android.app.model.UserAnswer import org.oppia.android.app.model.UserAssessmentPerformance import org.oppia.android.domain.classify.AnswerClassificationController import org.oppia.android.domain.classify.ClassificationResult.OutcomeWithMisconception +import org.oppia.android.domain.hintsandsolution.HintHandler import org.oppia.android.domain.oppialogger.exceptions.ExceptionsController import org.oppia.android.domain.question.QuestionAssessmentProgress.TrainStage import org.oppia.android.util.data.AsyncDataSubscriptionManager @@ -48,16 +48,20 @@ class QuestionAssessmentProgressController @Inject constructor( private val dataProviders: DataProviders, private val asyncDataSubscriptionManager: AsyncDataSubscriptionManager, private val answerClassificationController: AnswerClassificationController, - private val exceptionsController: ExceptionsController -) { + private val exceptionsController: ExceptionsController, + private val hintHandlerFactory: HintHandler.Factory +) : HintHandler.HintMonitor { // TODO(#247): Add support for populating the list of skill IDs to review at the end of the // training session. // TODO(#248): Add support for the assessment ending prematurely due to learner demonstrating // sufficient proficiency. private val progress = QuestionAssessmentProgress() + private lateinit var hintHandler: HintHandler private val progressLock = ReentrantLock() - @Inject internal lateinit var scoreCalculatorFactory: QuestionAssessmentCalculation.Factory + + @Inject + internal lateinit var scoreCalculatorFactory: QuestionAssessmentCalculation.Factory private val currentQuestionDataProvider: NestedTransformedDataProvider = createCurrentQuestionDataProvider(createEmptyQuestionsListDataProvider()) @@ -69,6 +73,7 @@ class QuestionAssessmentProgressController @Inject constructor( "Cannot start a new training session until the previous one is completed." } + hintHandler = hintHandlerFactory.create(this) progress.advancePlayStageTo(TrainStage.LOADING_TRAINING_SESSION) currentQuestionDataProvider.setBaseDataProvider( questionsListDataProvider, @@ -90,6 +95,10 @@ class QuestionAssessmentProgressController @Inject constructor( } } + override fun onHelpIndexChanged() { + asyncDataSubscriptionManager.notifyChangeAsync(CREATE_CURRENT_QUESTION_DATA_PROVIDER_ID) + } + /** * Submits an answer to the current question and returns how the UI should respond to this answer. * The returned [LiveData] will only have at most two results posted: a pending result, and then a @@ -154,16 +163,22 @@ class QuestionAssessmentProgressController @Inject constructor( // Do not proceed unless the user submitted the correct answer. if (answeredQuestionOutcome.isCorrectAnswer) { progress.completeCurrentQuestion() - if (!progress.isAssessmentCompleted()) { + val newState = if (!progress.isAssessmentCompleted()) { // Only push the next state if the assessment isn't completed. - progress.stateDeck.pushState(progress.getNextState(), prohibitSameStateName = false) + progress.getNextState() } else { // Otherwise, push a synthetic state for the end of the session. - progress.stateDeck.pushState( - State.getDefaultInstance(), - prohibitSameStateName = false - ) + State.getDefaultInstance() } + progress.stateDeck.pushState(newState, prohibitSameStateName = false) + hintHandler.finishState(newState) + } else { + // Schedule a new hints or solution or show a new hint or solution immediately based on + // the current ephemeral state of the training session because a new wrong answer was + // submitted. + hintHandler.handleWrongAnswerSubmission( + computeCurrentEphemeralState().pendingState.wrongAnswerCount + ) } } finally { // Ensure that the user always returns to the VIEWING_STATE stage to avoid getting stuck @@ -182,11 +197,15 @@ class QuestionAssessmentProgressController @Inject constructor( } } - fun submitHintIsRevealed( - state: State, - hintIsRevealed: Boolean, - hintIndex: Int - ): LiveData> { + /** + * Notifies the controller that the user wishes to reveal a hint. + * + * @param hintIndex index of the hint that was revealed in the hint list of the current pending + * state + * @return a one-time [LiveData] that indicates success/failure of the operation (the actual + * payload of the result isn't relevant) + */ + fun submitHintIsRevealed(hintIndex: Int): LiveData> { try { progressLock.withLock { check(progress.trainStage != TrainStage.NOT_IN_TRAINING_SESSION) { @@ -198,16 +217,9 @@ class QuestionAssessmentProgressController @Inject constructor( check(progress.trainStage != TrainStage.SUBMITTING_ANSWER) { "Cannot submit an answer while another answer is pending." } - lateinit var hint: Hint try { - progress.stateDeck.submitHintRevealed(state, hintIsRevealed, hintIndex) - hint = progress.stateList.computeHintForResult( - state, - hintIsRevealed, - hintIndex - ) - progress.stateDeck.pushStateForHint(state, hintIndex) progress.trackHintViewed() + hintHandler.viewHint(hintIndex) } finally { // Ensure that the user always returns to the VIEWING_STATE stage to avoid getting stuck // in an 'always showing hint' situation. This can specifically happen if hint throws an @@ -215,7 +227,7 @@ class QuestionAssessmentProgressController @Inject constructor( progress.advancePlayStageTo(TrainStage.VIEWING_STATE) } asyncDataSubscriptionManager.notifyChangeAsync(CREATE_CURRENT_QUESTION_DATA_PROVIDER_ID) - return MutableLiveData(AsyncResult.success(hint)) + return MutableLiveData(AsyncResult.success(null)) } } catch (e: Exception) { exceptionsController.logNonFatalException(e) @@ -223,7 +235,13 @@ class QuestionAssessmentProgressController @Inject constructor( } } - fun submitSolutionIsRevealed(state: State): LiveData> { + /** + * Notifies the controller that the user has revealed the solution to the current state. + * + * @return a one-time [LiveData] that indicates success/failure of the operation (the actual + * payload of the result isn't relevant) + */ + fun submitSolutionIsRevealed(): LiveData> { try { progressLock.withLock { check(progress.trainStage != TrainStage.NOT_IN_TRAINING_SESSION) { @@ -235,13 +253,9 @@ class QuestionAssessmentProgressController @Inject constructor( check(progress.trainStage != TrainStage.SUBMITTING_ANSWER) { "Cannot submit an answer while another answer is pending." } - lateinit var solution: Solution try { - - progress.stateDeck.submitSolutionRevealed(state) - solution = progress.stateList.computeSolutionForResult(state) - progress.stateDeck.pushStateForSolution(state) progress.trackSolutionViewed() + hintHandler.viewSolution() } finally { // Ensure that the user always returns to the VIEWING_STATE stage to avoid getting stuck // in an 'always showing solution' situation. This can specifically happen if solution @@ -250,7 +264,7 @@ class QuestionAssessmentProgressController @Inject constructor( } asyncDataSubscriptionManager.notifyChangeAsync(CREATE_CURRENT_QUESTION_DATA_PROVIDER_ID) - return MutableLiveData(AsyncResult.success(solution)) + return MutableLiveData(AsyncResult.success(null)) } } catch (e: Exception) { exceptionsController.logNonFatalException(e) @@ -284,6 +298,9 @@ class QuestionAssessmentProgressController @Inject constructor( progress.stateDeck.navigateToNextState() // Track whether the learner has moved to a new card. if (progress.isViewingMostRecentQuestion()) { + // Update the hint state and maybe schedule new help when user moves to the pending top + // state. + hintHandler.navigateBackToLatestPendingState() progress.processNavigationToNewQuestion() } asyncDataSubscriptionManager.notifyChangeAsync(CREATE_CURRENT_QUESTION_DATA_PROVIDER_ID) @@ -337,14 +354,21 @@ class QuestionAssessmentProgressController @Inject constructor( } } - private suspend fun retrieveUserAssessmentPerformanceAsync(skillIdList: List): - AsyncResult { - progressLock.withLock { - val scoreCalculator = - scoreCalculatorFactory.create(skillIdList, progress.questionSessionMetrics) - return AsyncResult.success(scoreCalculator.computeAll()) - } + private fun computeCurrentEphemeralState(): EphemeralState { + val helpIndex = hintHandler.getCurrentHelpIndex() + return progress.stateDeck.getCurrentEphemeralState(helpIndex) + } + + @Suppress("RedundantSuspendModifier") + private suspend fun retrieveUserAssessmentPerformanceAsync( + skillIdList: List + ): AsyncResult { + progressLock.withLock { + val scoreCalculator = + scoreCalculatorFactory.create(skillIdList, progress.questionSessionMetrics) + return AsyncResult.success(scoreCalculator.computeAll()) } + } private fun createCurrentQuestionDataProvider( questionsListDataProvider: DataProvider> @@ -385,10 +409,9 @@ class QuestionAssessmentProgressController @Inject constructor( } private fun retrieveEphemeralQuestionState(questionsList: List): EphemeralQuestion { - val ephemeralState = progress.stateDeck.getCurrentEphemeralState() val currentQuestionIndex = progress.getCurrentQuestionIndex() val ephemeralQuestionBuilder = EphemeralQuestion.newBuilder() - .setEphemeralState(ephemeralState) + .setEphemeralState(computeCurrentEphemeralState()) .setCurrentQuestionIndex(currentQuestionIndex) .setTotalQuestionCount(progress.getTotalQuestionCount()) .setInitialTotalQuestionCount(progress.getTotalQuestionCount()) @@ -401,6 +424,8 @@ class QuestionAssessmentProgressController @Inject constructor( private fun initializeAssessment(questionsList: List) { check(questionsList.isNotEmpty()) { "Cannot start a training session with zero questions." } progress.initialize(questionsList) + // Update hint state to schedule task to show new help. + hintHandler.startWatchingForHintsInNewState(progress.stateDeck.getCurrentState()) } /** Returns a temporary [DataProvider] that always provides an empty list of [Question]s. */ diff --git a/domain/src/main/java/org/oppia/android/domain/state/StateDeck.kt b/domain/src/main/java/org/oppia/android/domain/state/StateDeck.kt index 9bb1fb28bc8..25bfc89898f 100644 --- a/domain/src/main/java/org/oppia/android/domain/state/StateDeck.kt +++ b/domain/src/main/java/org/oppia/android/domain/state/StateDeck.kt @@ -5,9 +5,8 @@ import org.oppia.android.app.model.CompletedState import org.oppia.android.app.model.CompletedStateInCheckpoint import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.ExplorationCheckpoint -import org.oppia.android.app.model.Hint +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.PendingState -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.State import org.oppia.android.app.model.SubtitledHtml import org.oppia.android.app.model.UserAnswer @@ -25,24 +24,14 @@ internal class StateDeck internal constructor( private var pendingTopState: State = initialState private val previousStates: MutableList = ArrayList() private val currentDialogInteractions: MutableList = ArrayList() - private val hintList: MutableList = ArrayList() - private lateinit var solution: Solution private var stateIndex: Int = 0 - // The value -1 indicates that hint has not been revealed yet. - private var revealedHintIndex: Int = -1 - private var solutionIsRevealed: Boolean = false /** Resets this deck to a new, specified initial [State]. */ internal fun resetDeck(initialState: State) { pendingTopState = initialState previousStates.clear() currentDialogInteractions.clear() - hintList.clear() stateIndex = 0 - // Initialize the variable revealedHintIndex with -1 to indicate that no hint has been - // revealed yet. - revealedHintIndex = -1 - solutionIsRevealed = false } /** Navigates to the previous State in the deck, or fails if this isn't possible. */ @@ -72,14 +61,22 @@ internal class StateDeck internal constructor( /** Returns the index of the current selected card of the deck. */ internal fun getTopStateIndex(): Int = stateIndex + /** Returns the current [State] being viewed by the learner. */ + internal fun getCurrentState(): State { + return when { + isCurrentStateTopOfDeck() -> pendingTopState + else -> previousStates[stateIndex].state + } + } + /** Returns the current [EphemeralState] the learner is viewing. */ - internal fun getCurrentEphemeralState(): EphemeralState { + internal fun getCurrentEphemeralState(helpIndex: HelpIndex): EphemeralState { // Note that the terminal state is evaluated first since it can only return true if the current state is the top // of the deck, and that state is the terminal one. Otherwise the terminal check would never be triggered since // the second case assumes the top of the deck must be pending. return when { isCurrentStateTerminal() -> getCurrentTerminalState() - stateIndex == previousStates.size -> getCurrentPendingState() + isCurrentStateTopOfDeck() -> getCurrentPendingState(helpIndex) else -> getPreviousState() } } @@ -115,47 +112,7 @@ internal class StateDeck internal constructor( .setCompletedState(CompletedState.newBuilder().addAllAnswer(currentDialogInteractions)) .build() currentDialogInteractions.clear() - hintList.clear() pendingTopState = state - // Re-initialize the variable revealedHintIndex with -1 to indicate that no hint has been - // revealed on the new pendingTopState. - revealedHintIndex = -1 - solutionIsRevealed = false - } - - internal fun pushStateForHint(state: State, hintIndex: Int): EphemeralState { - val interactionBuilder = state.interaction.toBuilder().setHint( - hintIndex, - hintList.get(0) - ) - val newState = state.toBuilder().setInteraction(interactionBuilder).build() - val ephemeralState = EphemeralState.newBuilder() - .setState(newState) - .setHasPreviousState(!isCurrentStateInitial()) - .setPendingState( - PendingState.newBuilder().addAllWrongAnswer(currentDialogInteractions).addAllHint(hintList) - ) - .build() - pendingTopState = newState - hintList.clear() - // Increment the value of revealHintIndex by 1 every-time a new hint is revealed. - revealedHintIndex++ - return ephemeralState - } - - internal fun pushStateForSolution(state: State): EphemeralState { - val interactionBuilder = state.interaction.toBuilder().setSolution(solution) - val newState = state.toBuilder().setInteraction(interactionBuilder).build() - val ephemeralState = EphemeralState.newBuilder() - .setState(newState) - .setHasPreviousState(!isCurrentStateInitial()) - .setPendingState( - PendingState.newBuilder().addAllWrongAnswer(currentDialogInteractions).addAllHint(hintList) - ) - .build() - pendingTopState = newState - solutionIsRevealed = true - return ephemeralState } /** @@ -172,22 +129,6 @@ internal class StateDeck internal constructor( .build() } - internal fun submitHintRevealed(state: State, hintIsRevealed: Boolean, hintIndex: Int) { - hintList += Hint.newBuilder() - .setHintIsRevealed(hintIsRevealed) - .setHintContent(state.interaction.getHint(hintIndex).hintContent) - .build() - } - - internal fun submitSolutionRevealed(state: State) { - solution = Solution.newBuilder() - .setSolutionIsRevealed(true) - .setAnswerIsExclusive(state.interaction.solution.answerIsExclusive) - .setCorrectAnswer(state.interaction.solution.correctAnswer) - .setExplanation(state.interaction.solution.explanation) - .build() - } - /** * Returns an [ExplorationCheckpoint] which contains all the latest values of variables of the * [StateDeck] that are used in light weight checkpointing. @@ -195,7 +136,8 @@ internal class StateDeck internal constructor( internal fun createExplorationCheckpoint( explorationVersion: Int, explorationTitle: String, - timestamp: Long + timestamp: Long, + helpIndex: HelpIndex ): ExplorationCheckpoint { return ExplorationCheckpoint.newBuilder().apply { addAllCompletedStatesInCheckpoint( @@ -207,22 +149,23 @@ internal class StateDeck internal constructor( } ) pendingStateName = pendingTopState.name - hintIndex = revealedHintIndex addAllPendingUserAnswers(currentDialogInteractions) - this.solutionIsRevealed = this@StateDeck.solutionIsRevealed this.stateIndex = this@StateDeck.stateIndex this.explorationVersion = explorationVersion this.explorationTitle = explorationTitle timestampOfFirstCheckpoint = timestamp + this.helpIndex = helpIndex }.build() } - private fun getCurrentPendingState(): EphemeralState { + private fun getCurrentPendingState(helpIndex: HelpIndex): EphemeralState { return EphemeralState.newBuilder() .setState(pendingTopState) .setHasPreviousState(!isCurrentStateInitial()) .setPendingState( - PendingState.newBuilder().addAllWrongAnswer(currentDialogInteractions).addAllHint(hintList) + PendingState.newBuilder() + .addAllWrongAnswer(currentDialogInteractions) + .setHelpIndex(helpIndex) ) .build() } diff --git a/domain/src/main/java/org/oppia/android/domain/state/StateGraph.kt b/domain/src/main/java/org/oppia/android/domain/state/StateGraph.kt index 0e41e54efd6..deb47cea13a 100644 --- a/domain/src/main/java/org/oppia/android/domain/state/StateGraph.kt +++ b/domain/src/main/java/org/oppia/android/domain/state/StateGraph.kt @@ -1,9 +1,7 @@ package org.oppia.android.domain.state import org.oppia.android.app.model.AnswerOutcome -import org.oppia.android.app.model.Hint import org.oppia.android.app.model.Outcome -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.State /** @@ -39,28 +37,4 @@ internal class StateGraph internal constructor( } return answerOutcomeBuilder.build() } - - /** Returns an [Hint] based on the current state and revealed [Hint] from the learner's answer. */ - internal fun computeHintForResult( - currentState: State, - hintIsRevealed: Boolean, - hintIndex: Int - ): Hint { - return Hint.newBuilder() - .setHintIsRevealed(hintIsRevealed) - .setHintContent(currentState.interaction.getHint(hintIndex).hintContent) - .setState(currentState) - .build() - } - - /** Returns an [Solution] based on the current state and revealed [Solution] from the learner's answer. */ - internal fun computeSolutionForResult( - currentState: State - ): Solution { - return Solution.newBuilder() - .setSolutionIsRevealed(true) - .setAnswerIsExclusive(currentState.interaction.solution.answerIsExclusive) - .setCorrectAnswer(currentState.interaction.solution.correctAnswer) - .setExplanation(currentState.interaction.solution.explanation).build() - } } diff --git a/domain/src/main/java/org/oppia/android/domain/state/StateList.kt b/domain/src/main/java/org/oppia/android/domain/state/StateList.kt index 4db24a9cee6..57459e6d727 100644 --- a/domain/src/main/java/org/oppia/android/domain/state/StateList.kt +++ b/domain/src/main/java/org/oppia/android/domain/state/StateList.kt @@ -1,10 +1,8 @@ package org.oppia.android.domain.state import org.oppia.android.app.model.AnsweredQuestionOutcome -import org.oppia.android.app.model.Hint import org.oppia.android.app.model.Outcome import org.oppia.android.app.model.Question -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.State /** @@ -36,28 +34,4 @@ internal class StateList( .setIsCorrectAnswer(outcome.labelledAsCorrect) .build() } - - /** Returns an [Hint] based on the current state and revealed [Hint] from the learner's answer. */ - internal fun computeHintForResult( - currentState: State, - hintIsRevealed: Boolean, - hintIndex: Int - ): Hint { - return Hint.newBuilder() - .setHintIsRevealed(hintIsRevealed) - .setHintContent(currentState.interaction.getHint(hintIndex).hintContent) - .setState(currentState) - .build() - } - - /** Returns an [Solution] based on the current state and revealed [Solution] from the learner's answer. */ - internal fun computeSolutionForResult( - currentState: State - ): Solution { - return Solution.newBuilder() - .setSolutionIsRevealed(true) - .setAnswerIsExclusive(currentState.interaction.solution.answerIsExclusive) - .setCorrectAnswer(currentState.interaction.solution.correctAnswer) - .setExplanation(currentState.interaction.solution.explanation).build() - } } diff --git a/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationDataControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationDataControllerTest.kt index 639f617f6d3..42e073c1647 100644 --- a/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationDataControllerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationDataControllerTest.kt @@ -35,6 +35,8 @@ import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModu import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageDatabaseSize +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.topic.FRACTIONS_EXPLORATION_ID_0 import org.oppia.android.domain.topic.FRACTIONS_EXPLORATION_ID_1 @@ -343,7 +345,8 @@ class ExplorationDataControllerTest { DragDropSortInputModule::class, InteractionsModule::class, TestLogReportingModule::class, ImageClickInputModule::class, LogStorageModule::class, TestDispatcherModule::class, RatioInputModule::class, RobolectricModule::class, FakeOppiaClockModule::class, - TestExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class + TestExplorationStorageModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionProdModule::class, NetworkConnectionUtilDebugModule::class ] ) interface TestApplicationComponent : DataProvidersInjector { diff --git a/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt index 09ef21767fd..6279493d8b7 100644 --- a/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt @@ -7,6 +7,7 @@ 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 com.google.common.truth.extensions.proto.LiteProtoTruth.assertThat import dagger.BindsInstance import dagger.Component import dagger.Module @@ -33,14 +34,13 @@ import org.oppia.android.app.model.EphemeralState.StateTypeCase.PENDING_STATE import org.oppia.android.app.model.EphemeralState.StateTypeCase.TERMINAL_STATE import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.Fraction -import org.oppia.android.app.model.Hint +import org.oppia.android.app.model.HelpIndex import org.oppia.android.app.model.InteractionObject import org.oppia.android.app.model.ListOfSetsOfTranslatableHtmlContentIds import org.oppia.android.app.model.Point2d import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.RatioExpression import org.oppia.android.app.model.SetOfTranslatableHtmlContentIds -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.TranslatableHtmlContentId import org.oppia.android.app.model.UserAnswer import org.oppia.android.domain.classify.InteractionsModule @@ -56,6 +56,10 @@ import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationCheckpointController import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageDatabaseSize +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule +import org.oppia.android.domain.hintsandsolution.isHintRevealed +import org.oppia.android.domain.hintsandsolution.isSolutionRevealed import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.topic.TEST_EXPLORATION_ID_2 import org.oppia.android.domain.topic.TEST_EXPLORATION_ID_4 @@ -88,6 +92,7 @@ import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode import java.io.FileNotFoundException +import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton @@ -148,10 +153,10 @@ class ExplorationProgressControllerTest { lateinit var mockAsyncAnswerOutcomeObserver: Observer> @Mock - lateinit var mockAsyncHintObserver: Observer> + lateinit var mockAsyncHintObserver: Observer> @Mock - lateinit var mockAsyncSolutionObserver: Observer> + lateinit var mockAsyncSolutionObserver: Observer> @Captor lateinit var currentStateResultCaptor: ArgumentCaptor> @@ -1046,7 +1051,7 @@ class ExplorationProgressControllerTest { } @Test - fun testRevealHint_forWrongAnswer_showHint_returnHintIsRevealed() { + fun testRevealHint_forWrongAnswers_showHint_returnHintIsRevealed() { subscribeToCurrentStateToAllowExplorationToLoad() playExploration( profileId.internalId, @@ -1056,7 +1061,10 @@ class ExplorationProgressControllerTest { shouldSavePartialProgress = false ) navigateToPrototypeFractionInputState() + // Submit 2 wrong answers to trigger a hint becoming available. submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + verifyOperationSucceeds(explorationProgressController.submitHintIsRevealed(hintIndex = 0)) // Verify that the current state updates. It should stay pending, on submission of wrong answer. verify( @@ -1066,32 +1074,14 @@ class ExplorationProgressControllerTest { assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() val currentState = currentStateResultCaptor.value.getOrThrow() - val result = explorationProgressController.submitHintIsRevealed( - state = currentState.state, - hintIsRevealed = true, - hintIndex = 0, - ) - result.observeForever(mockAsyncHintObserver) - testCoroutineDispatchers.runCurrent() - - assertThat(currentState.stateTypeCase).isEqualTo(PENDING_STATE) - val hintAndSolution = currentState.state.interaction.getHint(0) + assertThat(currentState.stateTypeCase).isEqualTo(PENDING_STATE) assertThat(hintAndSolution.hintContent.html).contains("Remember that two halves") - - // Verify that the current state updates. Hint revealed is true. - verify( - mockCurrentStateLiveDataObserver, - atLeastOnce() - ).onChanged(currentStateResultCaptor.capture()) - assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() - val updatedState = currentStateResultCaptor.value.getOrThrow() - - assertThat(updatedState.state.interaction.getHint(0).hintIsRevealed).isTrue() + assertThat(currentState.isHintRevealed(0)).isTrue() } @Test - fun testRevealSolution_forWrongAnswer_showSolution_returnSolutionIsRevealed() { + fun testRevealSolution_triggeredSolution_showSolution_returnSolutionIsRevealed() { subscribeToCurrentStateToAllowExplorationToLoad() playExploration( profileId.internalId, @@ -1101,7 +1091,13 @@ class ExplorationProgressControllerTest { shouldSavePartialProgress = false ) navigateToPrototypeFractionInputState() + // Submit 2 wrong answers to trigger the hint. + submitWrongAnswerForPrototypeState2() submitWrongAnswerForPrototypeState2() + // Reveal the hint, then submit another wrong answer to trigger the solution. + verifyOperationSucceeds(explorationProgressController.submitHintIsRevealed(hintIndex = 0)) + submitWrongAnswerForPrototypeState2() + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) // Verify that the current state updates. It should stay pending, on submission of wrong answer. verify( @@ -1111,7 +1107,7 @@ class ExplorationProgressControllerTest { assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() val currentState = currentStateResultCaptor.value.getOrThrow() - val result = explorationProgressController.submitSolutionIsRevealed(currentState.state) + val result = explorationProgressController.submitSolutionIsRevealed() result.observeForever(mockAsyncSolutionObserver) testCoroutineDispatchers.runCurrent() @@ -1125,7 +1121,221 @@ class ExplorationProgressControllerTest { assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() val updatedState = currentStateResultCaptor.value.getOrThrow() - assertThat(updatedState.state.interaction.solution.solutionIsRevealed).isTrue() + assertThat(updatedState.isSolutionRevealed()).isTrue() + } + + @Test + fun testHintsAndSolution_noHintVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + + // Verify that the helpIndex.IndexTypeCase is equal to INDEX_TYPE_NOT_SET because no hint + // is visible yet. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.INDEXTYPE_NOT_SET) + } + + @Test + fun testHintsAndSolution_wait60Seconds_unrevealedHintIsVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + // Make the first hint visible by submitting two wrong answers. + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(60)) + testCoroutineDispatchers.runCurrent() + + // Verify that the helpIndex.IndexTypeCase is equal AVAILABLE_NEXT_HINT_HINT_INDEX because a new + // unrevealed hint is visible. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.isHintRevealed(0)).isFalse() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX) + assertThat(currentState.pendingState.helpIndex.nextAvailableHintIndex).isEqualTo(0) + } + + @Test + fun testHintsAndSolution_submitTwoWrongAnswers_unrevealedHintIsVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + // Make the first hint visible by submitting two wrong answers. + submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + + // Verify that the helpIndex.IndexTypeCase is equal AVAILABLE_NEXT_HINT_HINT_INDEX because a new + // unrevealed hint is visible. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.isHintRevealed(0)).isFalse() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.NEXT_AVAILABLE_HINT_INDEX) + assertThat(currentState.pendingState.helpIndex.nextAvailableHintIndex).isEqualTo(0) + } + + @Test + fun testHintsAndSolution_revealedHintIsVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + + val result = explorationProgressController.submitHintIsRevealed(hintIndex = 0) + result.observeForever(mockAsyncHintObserver) + testCoroutineDispatchers.runCurrent() + + // Verify that the helpIndex.IndexTypeCase is equal LATEST_REVEALED_HINT_INDEX because a new + // revealed hint is visible. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.isHintRevealed(0)).isTrue() + assertThat(currentState.isSolutionRevealed()).isFalse() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.LATEST_REVEALED_HINT_INDEX) + assertThat(currentState.pendingState.helpIndex.latestRevealedHintIndex).isEqualTo(0) + } + + @Test + fun testHintsAndSolution_allHintsVisible_wait30Seconds_solutionVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + + val result = explorationProgressController.submitHintIsRevealed(hintIndex = 0) + result.observeForever(mockAsyncHintObserver) + testCoroutineDispatchers.runCurrent() + + // The solution should be visible after 30 seconds of the last hint being reveled. + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(30)) + testCoroutineDispatchers.runCurrent() + + // Verify that the helpIndex.IndexTypeCase is equal SHOW_SOLUTION because unrevealed solution is + // visible. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.isHintRevealed(0)).isTrue() + assertThat(currentState.isSolutionRevealed()).isFalse() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.SHOW_SOLUTION) + } + + @Test + fun testHintAndSol_hintsVisible_submitWrongAns_wait10Second_solVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + + val result = explorationProgressController.submitHintIsRevealed(hintIndex = 0) + result.observeForever(mockAsyncHintObserver) + testCoroutineDispatchers.runCurrent() + + submitWrongAnswerForPrototypeState2() + // The solution should be visible after 10 seconds becuase one wrong answer was submitted. + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) + testCoroutineDispatchers.runCurrent() + + // Verify that the helpIndex.IndexTypeCase is equal SHOW_SOLUTION because unrevealed solution is + // visible. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.isHintRevealed(0)).isTrue() + assertThat(currentState.isSolutionRevealed()).isFalse() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.SHOW_SOLUTION) + } + + @Test + fun testHintsAndSolution_revealedSolutionIsVisible_checkHelpIndexIsCorrect() { + subscribeToCurrentStateToAllowExplorationToLoad() + playExploration( + profileId.internalId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = true + ) + playThroughPrototypeState1AndMoveToNextState() + submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + + val hintResult = explorationProgressController.submitHintIsRevealed(hintIndex = 0) + hintResult.observeForever(mockAsyncHintObserver) + testCoroutineDispatchers.runCurrent() + + // The solution should be visible after 30 seconds of the last hint being reveled. + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(30)) + testCoroutineDispatchers.runCurrent() + + val solutionResult = explorationProgressController.submitSolutionIsRevealed() + solutionResult.observeForever(mockAsyncSolutionObserver) + testCoroutineDispatchers.runCurrent() + + // Verify that the helpIndex.IndexTypeCase is equal EVERYTHING_IS_REVEALED because a new the + // solution has been revealed. + verify(mockCurrentStateLiveDataObserver, atLeastOnce()) + .onChanged(currentStateResultCaptor.capture()) + assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() + val currentState = currentStateResultCaptor.value.getOrThrow() + assertThat(currentState.isHintRevealed(0)).isTrue() + assertThat(currentState.isSolutionRevealed()).isTrue() + assertThat(currentState.pendingState.helpIndex.indexTypeCase) + .isEqualTo(HelpIndex.IndexTypeCase.EVERYTHING_REVEALED) } @Test @@ -2028,6 +2238,8 @@ class ExplorationProgressControllerTest { shouldSavePartialProgress = true ) navigateToPrototypeFractionInputState() + // Submit 2 wrong answers to trigger the hint. + submitWrongAnswerForPrototypeState2() submitWrongAnswerForPrototypeState2() verify( @@ -2035,20 +2247,15 @@ class ExplorationProgressControllerTest { atLeastOnce() ).onChanged(currentStateResultCaptor.capture()) assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() - val currentState = currentStateResultCaptor.value.getOrThrow() - val result = explorationProgressController.submitHintIsRevealed( - state = currentState.state, - hintIsRevealed = true, - hintIndex = 0, - ) - result.observeForever(mockAsyncHintObserver) - testCoroutineDispatchers.runCurrent() + verifyOperationSucceeds(explorationProgressController.submitHintIsRevealed(hintIndex = 0)) - verifyCheckpointHasCorrectHintIndex( + verifyCheckpointHasCorrectHelpIndex( profileId, TEST_EXPLORATION_ID_2, - indexOfRevealedHint = 0 + helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() ) } @@ -2063,23 +2270,28 @@ class ExplorationProgressControllerTest { shouldSavePartialProgress = true ) navigateToPrototypeFractionInputState() + // Submit 2 wrong answers to trigger the hint. submitWrongAnswerForPrototypeState2() + submitWrongAnswerForPrototypeState2() + // Reveal the hint, then submit another wrong answer to trigger the solution. + verifyOperationSucceeds(explorationProgressController.submitHintIsRevealed(hintIndex = 0)) + submitWrongAnswerForPrototypeState2() + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) verify( mockCurrentStateLiveDataObserver, atLeastOnce() ).onChanged(currentStateResultCaptor.capture()) assertThat(currentStateResultCaptor.value.isSuccess()).isTrue() - val currentState = currentStateResultCaptor.value.getOrThrow() - val result = explorationProgressController.submitSolutionIsRevealed(currentState.state) - result.observeForever(mockAsyncSolutionObserver) - testCoroutineDispatchers.runCurrent() + verifyOperationSucceeds(explorationProgressController.submitSolutionIsRevealed()) - verifyCheckpointHasCorrectValueOfIsSolutionRevealed( + verifyCheckpointHasCorrectHelpIndex( profileId, TEST_EXPLORATION_ID_2, - isSolutionRevealed = true + helpIndex = HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() ) } @@ -2545,6 +2757,13 @@ class ExplorationProgressControllerTest { return UserAnswer.newBuilder().setAnswer(answer).setPlainAnswer(answer.toAnswerString()).build() } + private fun EphemeralState.isHintRevealed(hintIndex: Int): Boolean { + return pendingState.helpIndex.isHintRevealed(hintIndex, state.interaction.hintList) + } + + private fun EphemeralState.isSolutionRevealed(): Boolean = + pendingState.helpIndex.isSolutionRevealed() + private fun verifyCheckpointHasCorrectPendingStateName( profileId: ProfileId, explorationId: String, @@ -2614,33 +2833,10 @@ class ExplorationProgressControllerTest { .isEqualTo(stateIndex) } - private fun verifyCheckpointHasCorrectHintIndex( - profileId: ProfileId, - explorationId: String, - indexOfRevealedHint: Int - ) { - testCoroutineDispatchers.runCurrent() - reset(mockExplorationCheckpointObserver) - val explorationCheckpointLiveData = - explorationCheckpointController.retrieveExplorationCheckpoint( - profileId, - explorationId - ).toLiveData() - explorationCheckpointLiveData.observeForever(mockExplorationCheckpointObserver) - testCoroutineDispatchers.runCurrent() - - verify(mockExplorationCheckpointObserver, atLeastOnce()) - .onChanged(explorationCheckpointCaptor.capture()) - assertThat(explorationCheckpointCaptor.value.isSuccess()).isTrue() - - assertThat(explorationCheckpointCaptor.value.getOrThrow().hintIndex) - .isEqualTo(indexOfRevealedHint) - } - - private fun verifyCheckpointHasCorrectValueOfIsSolutionRevealed( + private fun verifyCheckpointHasCorrectHelpIndex( profileId: ProfileId, explorationId: String, - isSolutionRevealed: Boolean + helpIndex: HelpIndex ) { testCoroutineDispatchers.runCurrent() reset(mockExplorationCheckpointObserver) @@ -2656,8 +2852,7 @@ class ExplorationProgressControllerTest { .onChanged(explorationCheckpointCaptor.capture()) assertThat(explorationCheckpointCaptor.value.isSuccess()).isTrue() - assertThat(explorationCheckpointCaptor.value.getOrThrow().solutionIsRevealed) - .isEqualTo(isSolutionRevealed) + assertThat(explorationCheckpointCaptor.value.getOrThrow().helpIndex).isEqualTo(helpIndex) } /** @@ -2757,7 +2952,8 @@ class ExplorationProgressControllerTest { DragDropSortInputModule::class, InteractionsModule::class, TestLogReportingModule::class, ImageClickInputModule::class, LogStorageModule::class, TestDispatcherModule::class, RatioInputModule::class, RobolectricModule::class, FakeOppiaClockModule::class, - TestExplorationStorageModule::class, NetworkConnectionUtilDebugModule::class + TestExplorationStorageModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionProdModule::class, NetworkConnectionUtilDebugModule::class ] ) interface TestApplicationComponent : DataProvidersInjector { diff --git a/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HelpIndexExtensionsTest.kt b/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HelpIndexExtensionsTest.kt new file mode 100644 index 00000000000..a18f846f451 --- /dev/null +++ b/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HelpIndexExtensionsTest.kt @@ -0,0 +1,311 @@ +package org.oppia.android.domain.hintsandsolution + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.Hint +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode + +/** Tests for [HelpIndex] extensions. */ +@Suppress("FunctionName") +@RunWith(AndroidJUnit4::class) +@LooperMode(LooperMode.Mode.PAUSED) +@Config(manifest = Config.NONE) +class HelpIndexExtensionsTest { + @Suppress("PrivatePropertyName") + private val HINT_LIST_OF_SIZE_2 = listOf(Hint.getDefaultInstance(), Hint.getDefaultInstance()) + + @Suppress("PrivatePropertyName") + private val HINT_LIST_OF_SIZE_3 = listOf( + Hint.getDefaultInstance(), Hint.getDefaultInstance(), Hint.getDefaultInstance() + ) + + @Test + fun testIsHintRevealed_defaultHelpIndex_returnsFalse() { + val helpIndex = HelpIndex.getDefaultInstance() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, hintList = listOf()) + + // An unknown or initial HelpIndex state means no hints have yet been viewed. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsHintRevealed_availableHintIndex0_index0_hintListSize3_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_3) + + // This hint is available, but hasn't yet been viewed. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsHintRevealed_availableHintIndex1_index0_hintListSize3_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_3) + + // The next hint being available implies the previous must have been seen. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_availableHintIndex1_index1_hintListSize3_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 1, HINT_LIST_OF_SIZE_3) + + // This hint is available to view, but hasn't been yet. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsHintRevealed_availableHintIndex2_index0_hintListSize3_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 2 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_3) + + // Two hints from now is available, so this one must have been viewed. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_availableHintIndex2_index1_hintListSize3_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 2 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 1, HINT_LIST_OF_SIZE_3) + + // The next hint is available, so this one must have been viewed. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_availableHintIndex2_index2_hintListSize3_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 2 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 2, HINT_LIST_OF_SIZE_3) + + // This hint is available to view, but hasn't yet been viewed. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsHintRevealed_lastRevealedHintIndex0_index0_hintListSize3_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_3) + + // The revealed index matches the one being checked. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_lastRevealedHintIndex0_index1_hintListSize3_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 1, HINT_LIST_OF_SIZE_3) + + // This hint hasn't yet been revealed, but the previous one has. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsHintRevealed_lastRevealedHintIndex1_index0_hintListSize3_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_3) + + // The next hint has been revealed. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_lastRevealedHintIndex1_index1_hintListSize3_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 1, HINT_LIST_OF_SIZE_3) + + // This hint has been revealed. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_showSolution_index0_hintListSize2_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + showSolution = true + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_2) + + // A viewable solution means all previous hints must have been seen. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_showSolution_index1_hintListSize2_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + showSolution = true + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 1, HINT_LIST_OF_SIZE_2) + + // A viewable solution means all previous hints must have been seen. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_showSolution_index0_hintListSize0_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + showSolution = true + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, hintList = listOf()) + + // Despite the solution being visible, no hints means that no hints could have been viewed. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsHintRevealed_everythingRevealed_index0_hintListSize2_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, HINT_LIST_OF_SIZE_2) + + // Everything has been revealed including all past hints. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_everythingRevealed_index1_hintListSize2_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 1, HINT_LIST_OF_SIZE_2) + + // Everything has been revealed including all past hints. + assertThat(hintIsRevealed).isTrue() + } + + @Test + fun testIsHintRevealed_everythingRevealed_index0_hintListSize0_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + + val hintIsRevealed = helpIndex.isHintRevealed(hintIndex = 0, hintList = listOf()) + + // Despite everything being visible, no hints means that no hints could have been viewed. + assertThat(hintIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_defaultHelpIndex_returnsFalse() { + val helpIndex = HelpIndex.getDefaultInstance() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // The default state indicates nothing has been viewed yet, including the solution. + assertThat(solutionIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_availableHint0_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // If a hint is available to view, the solution could not yet have been revealed. + assertThat(solutionIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_availableHint1_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // If a hint is available to view, the solution could not yet have been revealed. + assertThat(solutionIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_viewedHint0_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // If a hint was viewed, the solution might eventually be available to view but it evidently + // hasn't yet been revealed. + assertThat(solutionIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_viewedHint1_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // If a hint was viewed, the solution might eventually be available to view but it evidently + // hasn't yet been revealed. + assertThat(solutionIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_showSolution_returnsFalse() { + val helpIndex = HelpIndex.newBuilder().apply { + showSolution = true + }.build() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // The solution is now available to view, but it reportedly hasn't yet been revealed. + assertThat(solutionIsRevealed).isFalse() + } + + @Test + fun testIsSolutionRevealed_everythingIsRevealed_returnsTrue() { + val helpIndex = HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + + val solutionIsRevealed = helpIndex.isSolutionRevealed() + + // If everything has been revealed, that ensures the solution has also been revealed. + assertThat(solutionIsRevealed).isTrue() + } +} diff --git a/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HintHandlerImplTest.kt b/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HintHandlerImplTest.kt new file mode 100644 index 00000000000..7eeba4b44ff --- /dev/null +++ b/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HintHandlerImplTest.kt @@ -0,0 +1,1533 @@ +package org.oppia.android.domain.hintsandsolution + +import android.app.Application +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import com.google.common.truth.extensions.proto.LiteProtoTruth.assertThat +import dagger.BindsInstance +import dagger.Component +import dagger.Module +import dagger.Provides +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.reset +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.oppia.android.app.model.Exploration +import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.State +import org.oppia.android.domain.exploration.ExplorationRetriever +import org.oppia.android.testing.TestLogReportingModule +import org.oppia.android.testing.assertThrows +import org.oppia.android.testing.environment.TestEnvironmentConfig +import org.oppia.android.testing.robolectric.RobolectricModule +import org.oppia.android.testing.threading.TestCoroutineDispatchers +import org.oppia.android.testing.threading.TestDispatcherModule +import org.oppia.android.util.caching.LoadLessonProtosFromAssets +import org.oppia.android.util.data.DataProvidersInjector +import org.oppia.android.util.data.DataProvidersInjectorProvider +import org.oppia.android.util.logging.LoggerModule +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import java.util.concurrent.TimeUnit +import javax.inject.Inject +import javax.inject.Singleton + +/** Tests for [HintHandlerImpl]. */ +@Suppress("FunctionName") +@RunWith(AndroidJUnit4::class) +@LooperMode(LooperMode.Mode.PAUSED) +@Config(application = HintHandlerImplTest.TestApplication::class) +class HintHandlerImplTest { + @Rule + @JvmField + val mockitoRule: MockitoRule = MockitoJUnit.rule() + + @Mock + lateinit var mockHintMonitor: HintHandler.HintMonitor + + @Inject + lateinit var hintHandlerImplFactory: HintHandlerImpl.FactoryImpl + + @Inject + lateinit var explorationRetriever: ExplorationRetriever + + @Inject + lateinit var testCoroutineDispatchers: TestCoroutineDispatchers + + private lateinit var hintHandler: HintHandler + private val expWithNoHintsOrSolution by lazy { + explorationRetriever.loadExploration("test_single_interactive_state_exp_no_hints_no_solution") + } + private val expWithOneHintAndNoSolution by lazy { + explorationRetriever.loadExploration( + "test_single_interactive_state_exp_with_one_hint_and_no_solution" + ) + } + private val expWithOneHintAndSolution by lazy { + explorationRetriever.loadExploration( + "test_single_interactive_state_exp_with_one_hint_and_solution" + ) + } + private val expWithNoHintsAndOneSolution by lazy { + explorationRetriever.loadExploration("test_single_interactive_state_exp_with_only_solution") + } + private val expWithHintsAndSolution by lazy { + explorationRetriever.loadExploration( + "test_single_interactive_state_exp_with_hints_and_solution" + ) + } + + @Before + fun setUp() { + setUpTestApplicationComponent() + // Use the direct HintHandler factory to avoid testing the module setup. + hintHandler = hintHandlerImplFactory.create(mockHintMonitor) + } + + /* Tests for startWatchingForHintsInNewState */ + + @Test + fun testStartWatchingForHints_stateWithoutHints_callsMonitor() { + val state = expWithNoHintsOrSolution.getInitialState() + + hintHandler.startWatchingForHintsInNewState(state) + + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testStartWatchingForHints_stateWithoutHints_helpIndexIsEmpty() { + val state = expWithNoHintsOrSolution.getInitialState() + + hintHandler.startWatchingForHintsInNewState(state) + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testStartWatchingForHints_stateWithoutHints_wait60Seconds_monitorNotCalledAgain() { + val state = expWithNoHintsOrSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + waitFor60Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testStartWatchingForHints_stateWithoutHints_wait60Seconds_helpIndexIsEmpty() { + val state = expWithNoHintsOrSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + waitFor60Seconds() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testStartWatchingForHints_stateWithHints_callsMonitor() { + val state = expWithHintsAndSolution.getInitialState() + + hintHandler.startWatchingForHintsInNewState(state) + + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testStartWatchingForHints_stateWithHints_helpIndexIsEmpty() { + val state = expWithHintsAndSolution.getInitialState() + + hintHandler.startWatchingForHintsInNewState(state) + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testStartWatchingForHints_stateWithHints_wait10Seconds_doesNotCallMonitorAgain() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + waitFor10Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testStartWatchingForHints_stateWithHints_wait30Seconds_doesNotCallMonitorAgain() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + waitFor30Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testStartWatchingForHints_stateWithHints_wait60Seconds_callsMonitorAgain() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + waitFor60Seconds() + + // Verify that the monitor is called again (since there's a hint now available). + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testStartWatchingForHints_stateWithHints_wait60Seconds_firstHintIsAvailable() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + waitFor60Seconds() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + /* Tests for finishState */ + + @Test + fun testFinishState_defaultState_callsMonitor() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + // Simulate the default instance case (which can occur specifically for questions). + hintHandler.finishState(State.getDefaultInstance()) + + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testFinishState_defaultState_helpIndexIsEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + // Simulate the default instance case (which can occur specifically for questions). + hintHandler.finishState(State.getDefaultInstance()) + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testFinishState_defaultState_wait60Seconds_monitorNotCalledAgain() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.finishState(State.getDefaultInstance()) + reset(mockHintMonitor) + + waitFor60Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testFinishState_defaultState_wait60Seconds_helpIndexStaysEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.finishState(State.getDefaultInstance()) + reset(mockHintMonitor) + + waitFor60Seconds() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testFinishState_newStateWithHints_helpIndexIsEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + // Note that this is slightly suspect: normally, a state would be sourced from an independent + // question or from the same exploration. This tactic is taken to simplify the data structure + // requirements for the test, and because it should be more or less functionally equivalent. + hintHandler.finishState(expWithOneHintAndNoSolution.getInitialState()) + + // The help index should be reset. + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testFinishState_newStateWithHints_wait60Seconds_callsMonitorAgain() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.finishState(expWithOneHintAndNoSolution.getInitialState()) + reset(mockHintMonitor) + + waitFor60Seconds() + + // The index should be called again now that there's a new index. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testFinishState_previousStateFullyRevealed_newStateWithHints_wait60Seconds_indexHasNewHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealEverythingInMultiHintState() + hintHandler.finishState(expWithOneHintAndNoSolution.getInitialState()) + + waitFor60Seconds() + + // A new hint index should be revealed despite the entire previous state being completed (since + // the handler has been reset). + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testFinishState_newStateWithoutHints_wait60Seconds_doesNotCallMonitorAgain() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealEverythingInMultiHintState() + hintHandler.finishState(expWithNoHintsOrSolution.getInitialState()) + reset(mockHintMonitor) + + waitFor60Seconds() + + // Since the new state doesn't have any hints, the index will not change. + verifyNoMoreInteractions(mockHintMonitor) + } + + /* Tests for handleWrongAnswerSubmission */ + + @Test + fun testWrongAnswerSubmission_stateWithHints_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testWrongAnswerSubmission_stateWithHints_helpIndexStaysEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + @Test + fun testWrongAnswerSubmission_stateWithHints_wait10seconds_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + reset(mockHintMonitor) + + waitFor10Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testWrongAnswerSubmission_stateWithHints_wait30seconds_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + reset(mockHintMonitor) + + waitFor30Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testWrongAnswerSubmission_stateWithHints_wait60seconds_monitorCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + reset(mockHintMonitor) + + waitFor60Seconds() + + // A hint should now be available, so the monitor will be notified. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testWrongAnswerSubmission_stateWithHints_wait60seconds_helpIndexHasAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + waitFor60Seconds() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testWrongAnswerSubmission_twice_stateWithHints_monitorCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + // Simulate two answers being submitted subsequently. + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + // Submitting two wrong answers subsequently should immediately result in a hint being available. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testWrongAnswerSubmission_twice_stateWithHints_helpIndexHasAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + // Simulate two answers being submitted subsequently. + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testWrongAnswerSubmission_twice_stateWithoutHints_monitorNotCalled() { + val state = expWithNoHintsOrSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + // Simulate two answers being submitted subsequently. + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + // No notification should happen since the state doesn't have any hints. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testWrongAnswerSubmission_twice_stateWithoutHints_helpIndexIsEmpty() { + val state = expWithNoHintsOrSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + // Simulate two answers being submitted subsequently. + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + // No hint is available since the state has no hints. + assertThat(hintHandler.getCurrentHelpIndex()).isEqualToDefaultInstance() + } + + /* Tests for viewHint */ + + @Test + fun testViewHint_noHintAvailable_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewHint(hintIndex = 0) + } + + // No hint is available to reveal. + assertThat(exception).hasMessageThat().contains("Cannot reveal hint") + } + + @Test + fun testViewHint_hintAvailable_callsMonitor() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + reset(mockHintMonitor) + + hintHandler.viewHint(hintIndex = 0) + + // Viewing the hint should trigger a change in the help index. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testViewHint_hintAvailable_helpIndexUpdatedToShowHintShown() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + reset(mockHintMonitor) + + hintHandler.viewHint(hintIndex = 0) + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + ) + } + + @Test + fun testViewHint_hintAvailable_multiHintState_wait10Seconds_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + hintHandler.viewHint(hintIndex = 0) + reset(mockHintMonitor) + + waitFor10Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewHint_hintAvailable_multiHintState_wait30Seconds_monitorCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + hintHandler.viewHint(hintIndex = 0) + reset(mockHintMonitor) + + waitFor30Seconds() + + // 30 seconds is long enough to trigger a second hint to be available. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testViewHint_hintAvailable_multiHintState_wait30Seconds_helpIndexHasNewAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + hintHandler.viewHint(hintIndex = 0) + + waitFor30Seconds() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + ) + } + + @Test + fun testViewHint_hintAvailable_multiHintState_allHintsRevealed_indexShowsLastRevealedHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + ) + } + + @Test + fun testViewHint_multiHintState_allHintsRevealed_triggerSolution_indexShowsSolution() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + + triggerSolution() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testViewHint_hintAvailable_oneHintState_withSolution_wait10Sec_monitorNotCalled() { + val state = expWithOneHintAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + reset(mockHintMonitor) + + waitFor10Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewHint_hintAvailable_oneHintState_withSolution_wait30Sec_monitorCalled() { + val state = expWithOneHintAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + reset(mockHintMonitor) + + waitFor30Seconds() + + // The solution should now be available. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testViewHint_hintAvailable_oneHintState_withSolution_wait30Sec_indexShowsSolution() { + val state = expWithOneHintAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + + waitFor30Seconds() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testViewHint_hintAvailable_oneHintState_noSolution_wait10Sec_monitorNotCalled() { + val state = expWithOneHintAndNoSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + reset(mockHintMonitor) + + waitFor10Seconds() + + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewHint_hintAvailable_oneHintState_noSolution_wait30Sec_monitorNotCalled() { + val state = expWithOneHintAndNoSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + reset(mockHintMonitor) + + waitFor30Seconds() + + // The index is still unchanged since there's nothing left to see. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewHint_latestHintViewed_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewHint(hintIndex = 0) + } + + // No hint is available to reveal since it's already been revealed. + assertThat(exception).hasMessageThat().contains("Cannot reveal hint") + } + + @Test + fun testViewHint_solutionAvailable_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewHint(hintIndex = 0) + } + + // No hint is available to reveal since all hints have been revealed. + assertThat(exception).hasMessageThat().contains("Cannot reveal hint") + } + + @Test + fun testViewHint_everythingRevealed_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerAndRevealSolution() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewHint(hintIndex = 0) + } + + // No hint is available to reveal since everything has been revealed. + assertThat(exception).hasMessageThat().contains("Cannot reveal hint") + } + + /* Tests for viewSolution */ + + @Test + fun testViewSolution_nothingAvailable_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewSolution() + } + + // The solution is not yet available to be seen (no hints have been viewed). + assertThat(exception).hasMessageThat().contains("Cannot reveal solution") + } + + @Test + fun testViewSolution_hintAvailable_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewSolution() + } + + // The solution is not yet available to be seen (one hint is available, but hasn't been viewed). + assertThat(exception).hasMessageThat().contains("Cannot reveal solution") + } + + @Test + fun testViewSolution_hintViewed_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewSolution() + } + + // The solution is not yet available to be seen (one hint was viewed, but the solution isn't + // available yet). + assertThat(exception).hasMessageThat().contains("Cannot reveal solution") + } + + @Test + fun testViewSolution_allHintsViewed_solutionNotTriggered_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewSolution() + } + + // The solution is not yet available to be seen since the user hasn't triggered the solution to + // actually show up. + assertThat(exception).hasMessageThat().contains("Cannot reveal solution") + } + + @Test + fun testViewSolution_solutionAvailable_callsMonitor() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerSolution() + reset(mockHintMonitor) + + hintHandler.viewSolution() + + // The help index should change when the solution is revealed. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testViewSolution_solutionAvailable_helpIndexUpdatedToShowEverything() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerSolution() + + hintHandler.viewSolution() + + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + ) + } + + @Test + fun testViewSolution_solutionAvailable_wait10Sec_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerSolution() + hintHandler.viewSolution() + reset(mockHintMonitor) + + waitFor10Seconds() + + // There's nothing left to be revealed. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewSolution_solutionAvailable_wait30Sec_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerSolution() + hintHandler.viewSolution() + reset(mockHintMonitor) + + waitFor30Seconds() + + // There's nothing left to be revealed. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewSolution_solutionAvailable_wait60Sec_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerSolution() + hintHandler.viewSolution() + reset(mockHintMonitor) + + waitFor60Seconds() + + // There's nothing left to be revealed. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testViewSolution_everythingViewed_throwsException() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerAndRevealSolution() + + val exception = assertThrows(IllegalStateException::class) { + hintHandler.viewSolution() + } + + // The solution has already been revealed. + assertThat(exception).hasMessageThat().contains("Cannot reveal solution") + } + + /* Tests for navigateToPreviousState */ + + @Test + fun testNavigateToPreviousState_pendingHint_wait60Sec_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + hintHandler.navigateToPreviousState() + waitFor60Seconds() + + // The monitor should not be called since the user navigated away from the pending state. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testNavigateToPreviousState_multipleTimes_pendingHint_wait60Sec_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + reset(mockHintMonitor) + + // Simulate navigating back three states. + hintHandler.navigateToPreviousState() + hintHandler.navigateToPreviousState() + hintHandler.navigateToPreviousState() + waitFor60Seconds() + + // The monitor should not be called since the pending state isn't visible. + verifyNoMoreInteractions(mockHintMonitor) + } + + /* Tests for navigateBackToLatestPendingState */ + + @Test + fun testNavigateBackToLatestPendingState_fromPreviousState_pendingHint_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.navigateToPreviousState() + reset(mockHintMonitor) + + hintHandler.navigateBackToLatestPendingState() + + // The monitor should not be called immediately after returning to the pending state. + verifyNoMoreInteractions(mockHintMonitor) + } + + @Test + fun testNavigateBackToLatestPendingState_fromPreviousState_pendingHint_wait60Sec_monitorCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.navigateToPreviousState() + hintHandler.navigateBackToLatestPendingState() + reset(mockHintMonitor) + + waitFor60Seconds() + + // The hint should not be available since the user has waited for the counter to finish. + verify(mockHintMonitor).onHelpIndexChanged() + } + + @Test + fun testNavigateBackToLatestPendingState_fromPreviousState_waitRemainingTime_monitorNotCalled() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor30Seconds() + hintHandler.navigateToPreviousState() + hintHandler.navigateBackToLatestPendingState() + reset(mockHintMonitor) + + waitFor30Seconds() + + // Waiting half the necessary time is insufficient to show the hint (since the timer is not + // resumed, it's reset after returning the pending state). + verifyNoMoreInteractions(mockHintMonitor) + } + + /* + * Tests for getCurrentHelpIndex (more detailed state machine tests; some may be redundant + * with earlier tests). It's suggested to reference the state machine diagram laid out in + * HintHandler's class KDoc when inspecting the following tests. + */ + + @Test + fun testGetCurrentHelpIndex_initialState_isEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_wait10Sec_isEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_wait30Sec_isEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor30Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_wait60Sec_hasAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor60Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_oneWrongAnswer_isEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_oneWrongAnswer_wait10Sec_isEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_oneWrongAnswer_wait30Sec_isEmpty() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor30Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_oneWrongAnswer_wait60Sec_hasAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor60Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_twoWrongAnswers_hasAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_withAvailableHint_anotherWrongAnswer_hasSameAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerFirstHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_hasShownHintIndex() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_wait10Sec_hasShownHintIndex() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_wait30Sec_hasNewAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + waitFor30Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_oneWrongAnswer_hasShownHintIndex() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_oneWrongAnswer_wait10Sec_hasNewAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_twoWrongAnswers_hasShownHintIndex() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + // Multiple wrong answers do not force a hint to be shown except for the first hint. + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 0 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_viewAvailableHint_twoWrongAnswers_wait10Sec_hasNewAvailableHint() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + nextAvailableHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_noSolution_everythingRevealed() { + val state = expWithOneHintAndNoSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + triggerAndRevealFirstHint() + + // All hints have been viewed for this state, so nothing remains. + assertThat(hintHandler.getCurrentHelpIndex()).isEqualTo( + HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_lastIndexViewed() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_wait10Sec_lastIndexViewed() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_wait30Sec_canShowSolution() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + waitFor30Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_wait30Sec_revealSolution_everythingRevealed() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + waitFor30Seconds() + hintHandler.viewSolution() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_oneWrongAnswer_lastIndexViewed() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_oneWrongAnswer_wait10Sec_canShowSolution() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_twoWrongAnswers_lastIndexViewed() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + // Multiple subsequent wrong answers only affects the first hint. + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + latestRevealedHintIndex = 1 + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_allHintsViewed_twoWrongAnswers_wait10Sec_canShowSolution() { + val state = expWithHintsAndSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_isEmpty() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_wait10Sec_isEmpty() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_wait30Sec_isEmpty() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor30Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_wait60Sec_canShowSolution() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor60Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_oneWrongAnswer_isEmpty() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_oneWrongAnswer_wait10Sec_isEmpty() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor10Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_oneWrongAnswer_wait30Sec_isEmpty() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor30Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualToDefaultInstance() + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_oneWrongAnswer_wait60Sec_canShowSolution() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + waitFor60Seconds() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_twoWrongAnswers_canShowSolution() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 1) + hintHandler.handleWrongAnswerSubmission(wrongAnswerCount = 2) + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + showSolution = true + }.build() + ) + } + + @Test + fun testGetCurrentHelpIndex_onlySolution_triggeredAndRevealed_everythingIsRevealed() { + val state = expWithNoHintsAndOneSolution.getInitialState() + hintHandler.startWatchingForHintsInNewState(state) + waitFor60Seconds() + hintHandler.viewSolution() + + val helpIndex = hintHandler.getCurrentHelpIndex() + + assertThat(helpIndex).isEqualTo( + HelpIndex.newBuilder().apply { + everythingRevealed = true + }.build() + ) + } + + private fun Exploration.getInitialState(): State = statesMap.getValue(initStateName) + + private fun triggerFirstHint() = waitFor60Seconds() + + private fun triggerSecondHint() = waitFor30Seconds() + + private fun triggerSolution() = waitFor30Seconds() + + private fun triggerAndRevealFirstHint() { + triggerFirstHint() + hintHandler.viewHint(hintIndex = 0) + } + + private fun triggerAndRevealSecondHint() { + triggerSecondHint() + hintHandler.viewHint(hintIndex = 1) + } + + private fun triggerAndRevealSolution() { + triggerSolution() + hintHandler.viewSolution() + } + + private fun triggerAndRevealEverythingInMultiHintState() { + triggerAndRevealFirstHint() + triggerAndRevealSecondHint() + triggerAndRevealSolution() + } + + private fun waitFor10Seconds() = waitFor(seconds = 10) + + private fun waitFor30Seconds() = waitFor(seconds = 30) + + private fun waitFor60Seconds() = waitFor(seconds = 60) + + private fun waitFor(seconds: Long) { + // There's a weird quirk at the moment where the initial coroutine doesn't start without a + // runCurrent(). This seems a bit like a bug within the dispatchers; it should probably flush + // current tasks before advancing time. + // TODO(#3700): Fix this behavior (once fixed, 'runCurrent' should be able to be removed below). + testCoroutineDispatchers.runCurrent() + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(seconds)) + } + + private fun setUpTestApplicationComponent() { + ApplicationProvider.getApplicationContext().inject(this) + } + + // TODO(#89): Move this to a common test application component. + @Module + class TestModule { + @Provides + fun provideContext(application: Application): Context = application + + @Provides + @LoadLessonProtosFromAssets + fun provideLoadLessonProtosFromAssets(testEnvironmentConfig: TestEnvironmentConfig): Boolean = + testEnvironmentConfig.isUsingBazel() + } + + @Singleton + @Component( + modules = [ + TestModule::class, HintsAndSolutionProdModule::class, HintsAndSolutionConfigModule::class, + TestLogReportingModule::class, TestDispatcherModule::class, RobolectricModule::class, + LoggerModule::class, + ] + ) + interface TestApplicationComponent : DataProvidersInjector { + @Component.Builder + interface Builder { + @BindsInstance + fun setApplication(application: Application): Builder + + fun build(): TestApplicationComponent + } + + fun inject(hintHandlerImplTest: HintHandlerImplTest) + } + + class TestApplication : Application(), DataProvidersInjectorProvider { + private val component: TestApplicationComponent by lazy { + DaggerHintHandlerImplTest_TestApplicationComponent.builder() + .setApplication(this) + .build() + } + + fun inject(hintHandlerImplTest: HintHandlerImplTest) { + component.inject(hintHandlerImplTest) + } + + override fun getDataProvidersInjector(): DataProvidersInjector = component + } +} diff --git a/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModuleTest.kt b/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModuleTest.kt new file mode 100644 index 00000000000..0aa9edf7138 --- /dev/null +++ b/domain/src/test/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModuleTest.kt @@ -0,0 +1,91 @@ +package org.oppia.android.domain.hintsandsolution + +import android.app.Application +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import dagger.Binds +import dagger.BindsInstance +import dagger.Component +import dagger.Module +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.oppia.android.testing.TestLogReportingModule +import org.oppia.android.testing.robolectric.RobolectricModule +import org.oppia.android.testing.threading.TestDispatcherModule +import org.oppia.android.util.data.DataProvidersInjector +import org.oppia.android.util.data.DataProvidersInjectorProvider +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import javax.inject.Inject +import javax.inject.Singleton + +/** Tests for [HintsAndSolutionProdModule]. */ +@Suppress("FunctionName") +@RunWith(AndroidJUnit4::class) +@LooperMode(LooperMode.Mode.PAUSED) +@Config(application = HintsAndSolutionProdModuleTest.TestApplication::class) +class HintsAndSolutionProdModuleTest { + @Inject + lateinit var hintHandlerFactory: HintHandler.Factory + + @Before + fun setUp() { + setUpTestApplicationComponent() + } + + @Test + fun testHintHandlerFactoryInjection_constructNewHandler_providesFactoryForProdImplHandler() { + val hintHandler = hintHandlerFactory.create(object : HintHandler.HintMonitor { + override fun onHelpIndexChanged() {} + }) + + assertThat(hintHandler).isInstanceOf(HintHandlerImpl::class.java) + } + + private fun setUpTestApplicationComponent() { + ApplicationProvider.getApplicationContext().inject(this) + } + + // TODO(#89): Move this to a common test application component. + @Module + interface TestModule { + @Binds + fun provideContext(application: Application): Context + } + + @Singleton + @Component( + modules = [ + TestModule::class, HintsAndSolutionProdModule::class, HintsAndSolutionConfigModule::class, + TestLogReportingModule::class, TestDispatcherModule::class, RobolectricModule::class, + ] + ) + interface TestApplicationComponent : DataProvidersInjector { + @Component.Builder + interface Builder { + @BindsInstance + fun setApplication(application: Application): Builder + + fun build(): TestApplicationComponent + } + + fun inject(HintsAndSolutionProdModuleTest: HintsAndSolutionProdModuleTest) + } + + class TestApplication : Application(), DataProvidersInjectorProvider { + private val component: TestApplicationComponent by lazy { + DaggerHintsAndSolutionProdModuleTest_TestApplicationComponent.builder() + .setApplication(this) + .build() + } + + fun inject(HintsAndSolutionProdModuleTest: HintsAndSolutionProdModuleTest) { + component.inject(HintsAndSolutionProdModuleTest) + } + + override fun getDataProvidersInjector(): DataProvidersInjector = component + } +} diff --git a/domain/src/test/java/org/oppia/android/domain/question/QuestionAssessmentProgressControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/question/QuestionAssessmentProgressControllerTest.kt index bf7595ed7ac..015d60584d4 100644 --- a/domain/src/test/java/org/oppia/android/domain/question/QuestionAssessmentProgressControllerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/question/QuestionAssessmentProgressControllerTest.kt @@ -2,6 +2,7 @@ package org.oppia.android.domain.question import android.app.Application import android.content.Context +import androidx.lifecycle.LiveData import androidx.lifecycle.Observer import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -18,18 +19,18 @@ import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.atLeastOnce +import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule import org.oppia.android.app.model.AnsweredQuestionOutcome import org.oppia.android.app.model.EphemeralQuestion +import org.oppia.android.app.model.EphemeralState import org.oppia.android.app.model.EphemeralState.StateTypeCase.COMPLETED_STATE import org.oppia.android.app.model.EphemeralState.StateTypeCase.PENDING_STATE import org.oppia.android.app.model.EphemeralState.StateTypeCase.TERMINAL_STATE import org.oppia.android.app.model.FractionGrade -import org.oppia.android.app.model.Hint import org.oppia.android.app.model.InteractionObject -import org.oppia.android.app.model.Solution import org.oppia.android.app.model.UserAnswer import org.oppia.android.app.model.UserAssessmentPerformance import org.oppia.android.domain.classify.InteractionsModule @@ -43,6 +44,10 @@ import org.oppia.android.domain.classify.rules.numberwithunits.NumberWithUnitsRu import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModule import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule +import org.oppia.android.domain.hintsandsolution.isHintRevealed +import org.oppia.android.domain.hintsandsolution.isSolutionRevealed import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.topic.TEST_SKILL_ID_0 import org.oppia.android.domain.topic.TEST_SKILL_ID_1 @@ -65,9 +70,12 @@ import org.oppia.android.util.logging.LogLevel import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode +import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton +private const val TOLERANCE = 1e-5 + /** Tests for [QuestionAssessmentProgressController]. */ @RunWith(AndroidJUnit4::class) @LooperMode(LooperMode.Mode.PAUSED) @@ -104,9 +112,6 @@ class QuestionAssessmentProgressControllerTest { lateinit var mockScoreAndMasteryLiveDataObserver: Observer> - @Mock - lateinit var mockAsyncResultLiveDataObserver: Observer> - @Mock lateinit var mockAsyncNullableResultLiveDataObserver: Observer> @@ -114,10 +119,7 @@ class QuestionAssessmentProgressControllerTest { lateinit var mockAsyncAnswerOutcomeObserver: Observer> @Mock - lateinit var mockAsyncHintObserver: Observer> - - @Mock - lateinit var mockAsyncSolutionObserver: Observer> + lateinit var mockAsyncResultLiveDataObserver: Observer> @Captor lateinit var currentQuestionResultCaptor: ArgumentCaptor> @@ -663,8 +665,7 @@ class QuestionAssessmentProgressControllerTest { assertThat(currentQuestion.ephemeralState.stateTypeCase).isEqualTo(COMPLETED_STATE) val completedState = currentQuestion.ephemeralState.completedState assertThat(completedState.answerCount).isEqualTo(1) - assertThat(completedState.getAnswer(0).userAnswer.answer.real) - .isWithin(1e-5).of(5.0) + assertThat(completedState.getAnswer(0).userAnswer.answer.real).isWithin(TOLERANCE).of(5.0) assertThat(completedState.getAnswer(0).feedback.html).contains("That's correct!") } @@ -691,8 +692,7 @@ class QuestionAssessmentProgressControllerTest { assertThat(currentQuestion.ephemeralState.stateTypeCase).isEqualTo(PENDING_STATE) val pendingState = currentQuestion.ephemeralState.pendingState assertThat(pendingState.wrongAnswerCount).isEqualTo(1) - assertThat(pendingState.getWrongAnswer(0).userAnswer.answer.real) - .isWithin(1e-5).of(4.0) + assertThat(pendingState.getWrongAnswer(0).userAnswer.answer.real).isWithin(TOLERANCE).of(4.0) assertThat(pendingState.getWrongAnswer(0).feedback.html).isEmpty() } @@ -918,6 +918,7 @@ class QuestionAssessmentProgressControllerTest { startTrainingSession(TEST_SKILL_ID_LIST_01) submitTextInputAnswerAndMoveToNextQuestion("1/4") // question 0 submitMultipleChoiceAnswerAndMoveToNextQuestion(2) // question 1 + submitMultipleChoiceAnswerAndMoveToNextQuestion(2) // question 1 (again--second wrong answer) // Verify that we're on the second-to-last state of the second session. verify(mockCurrentQuestionLiveDataObserver, atLeastOnce()).onChanged( @@ -940,18 +941,14 @@ class QuestionAssessmentProgressControllerTest { assertThat(ephemeralQuestion.ephemeralState.stateTypeCase).isEqualTo(PENDING_STATE) assertThat(ephemeralQuestion.ephemeralState.pendingState.wrongAnswerCount) - .isEqualTo(1) + .isEqualTo(2) val hintAndSolution = ephemeralQuestion.ephemeralState.state.interaction.getHint(0) assertThat(hintAndSolution.hintContent.html).contains("Hint text will appear here") - val result = questionAssessmentProgressController.submitHintIsRevealed( - ephemeralQuestion.ephemeralState.state, - /* hintIsRevealed= */ true, - /* hintIndex= */ 0 + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) ) - result.observeForever(mockAsyncHintObserver) - testCoroutineDispatchers.runCurrent() // Verify that the current state updates. Hint revealed is true. verify( @@ -960,8 +957,7 @@ class QuestionAssessmentProgressControllerTest { ).onChanged(currentQuestionResultCaptor.capture()) assertThat(currentQuestionResultCaptor.value.isSuccess()).isTrue() val updatedState = currentQuestionResultCaptor.value.getOrThrow() - assertThat(updatedState.ephemeralState.state.interaction.getHint(0).hintIsRevealed) - .isTrue() + assertThat(updatedState.ephemeralState.isHintRevealed(0)).isTrue() } @Test @@ -974,6 +970,12 @@ class QuestionAssessmentProgressControllerTest { startTrainingSession(TEST_SKILL_ID_LIST_01) submitTextInputAnswerAndMoveToNextQuestion("1/3") // question 0 (wrong answer) + submitTextInputAnswerAndMoveToNextQuestion("1/3") // question 0 (wrong answer) + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) + ) + submitTextInputAnswerAndMoveToNextQuestion("1/3") // question 0 (wrong answer) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) verify(mockCurrentQuestionLiveDataObserver, atLeastOnce()).onChanged( currentQuestionResultCaptor.capture() @@ -981,16 +983,12 @@ class QuestionAssessmentProgressControllerTest { assertThat(currentQuestionResultCaptor.value.isSuccess()).isTrue() val currentQuestion = currentQuestionResultCaptor.value.getOrThrow() assertThat(currentQuestion.ephemeralState.stateTypeCase).isEqualTo(PENDING_STATE) - assertThat(currentQuestion.ephemeralState.pendingState.wrongAnswerCount).isEqualTo(1) + assertThat(currentQuestion.ephemeralState.pendingState.wrongAnswerCount).isEqualTo(3) val hintAndSolution = currentQuestion.ephemeralState.state.interaction.solution assertThat(hintAndSolution.correctAnswer.correctAnswer).contains("1/4") - val result = questionAssessmentProgressController.submitSolutionIsRevealed( - currentQuestion.ephemeralState.state - ) - result.observeForever(mockAsyncSolutionObserver) - testCoroutineDispatchers.runCurrent() + verifyOperationSucceeds(questionAssessmentProgressController.submitSolutionIsRevealed()) // Verify that the current state updates. Hint revealed is true. verify( @@ -999,7 +997,7 @@ class QuestionAssessmentProgressControllerTest { ).onChanged(currentQuestionResultCaptor.capture()) assertThat(currentQuestionResultCaptor.value.isSuccess()).isTrue() val updatedState = currentQuestionResultCaptor.value.getOrThrow() - assertThat(updatedState.ephemeralState.state.interaction.solution.solutionIsRevealed).isTrue() + assertThat(updatedState.ephemeralState.isSolutionRevealed()).isTrue() } @Test @@ -1011,6 +1009,10 @@ class QuestionAssessmentProgressControllerTest { // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) + viewHintForQuestion2() + submitIncorrectAnswerForQuestion2(4.0) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion2() submitCorrectAnswerForQuestion2() @@ -1040,7 +1042,10 @@ class QuestionAssessmentProgressControllerTest { // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) viewHintForQuestion2() + submitIncorrectAnswerForQuestion2(4.0) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion2() submitCorrectAnswerForQuestion2() @@ -1137,22 +1142,29 @@ class QuestionAssessmentProgressControllerTest { // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) viewHintForQuestion2() submitCorrectAnswerForQuestion2() // Question 3 // Submit question 3 wrong answer submitIncorrectAnswerForQuestion3("3/4") + submitIncorrectAnswerForQuestion3("3/4") + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) + ) + submitIncorrectAnswerForQuestion3("3/4") + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion3() submitCorrectAnswerForQuestion3() val userAssessmentPerformance = getExpectedGrade(TEST_SKILL_ID_LIST_01) val totalScore = FractionGrade.newBuilder().apply { - pointsReceived = 1.5 + pointsReceived = 1.4 totalPointsAvailable = 3.0 }.build() val skill0Score = FractionGrade.newBuilder().apply { - pointsReceived = 1.5 + pointsReceived = 1.4 totalPointsAvailable = 2.0 }.build() val skill1Score = FractionGrade.newBuilder().apply { @@ -1175,20 +1187,39 @@ class QuestionAssessmentProgressControllerTest { startTrainingSession(TEST_SKILL_ID_LIST_01) // Question 1 - // Submit question 1 wrong answer + // Submit question 1 wrong answer (a few extra wrong answers are added to reduce points). + submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) submitIncorrectAnswerForQuestion1(2) - viewSolutionForQuestion1() + submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) + viewHintForQuestion1(index = 0) + submitIncorrectAnswerForQuestion1(2) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) + viewHintForQuestion1(index = 1) submitCorrectAnswerForQuestion1() // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) + viewHintForQuestion2() + submitIncorrectAnswerForQuestion2(4.0) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion2() submitCorrectAnswerForQuestion2() // Question 3 // Submit question 3 wrong answer submitIncorrectAnswerForQuestion3("3/4") + submitIncorrectAnswerForQuestion3("3/4") + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) + ) + submitIncorrectAnswerForQuestion3("3/4") + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion3() submitCorrectAnswerForQuestion3() @@ -1214,7 +1245,7 @@ class QuestionAssessmentProgressControllerTest { } @Test - fun hintViewed_for2QuestionsWithWrongAnswer_returnScore2Point6Outof3() { + fun hintViewed_for2QuestionsWithWrongAnswer_returnScore2Point4Outof3() { setUpTestApplicationWithSeed(questionSeed = 0) subscribeToCurrentQuestionToAllowSessionToLoad() // This will generate question 1 (skill 0), question 2 (skill 0), and question 3 (skill 1) @@ -1223,12 +1254,14 @@ class QuestionAssessmentProgressControllerTest { // Question 1 // Submit question 1 wrong answer submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) viewHintForQuestion1(0) submitCorrectAnswerForQuestion1() // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) viewHintForQuestion2() submitCorrectAnswerForQuestion2() @@ -1237,11 +1270,11 @@ class QuestionAssessmentProgressControllerTest { val userAssessmentPerformance = getExpectedGrade(TEST_SKILL_ID_LIST_01) val totalScore = FractionGrade.newBuilder().apply { - pointsReceived = 2.6 + pointsReceived = 2.4 totalPointsAvailable = 3.0 }.build() val skill0Score = FractionGrade.newBuilder().apply { - pointsReceived = 1.6 + pointsReceived = 1.4 totalPointsAvailable = 2.0 }.build() val skill1Score = FractionGrade.newBuilder().apply { @@ -1257,7 +1290,7 @@ class QuestionAssessmentProgressControllerTest { } @Test - fun multipleHintsViewed_forQuestionsWithWrongAnswer_returnScore2Point7Outof3() { + fun multipleHintsViewed_forQuestionsWithWrongAnswer_returnScore2Point5Outof3() { setUpTestApplicationWithSeed(questionSeed = 0) subscribeToCurrentQuestionToAllowSessionToLoad() // This will generate question 1 (skill 0), question 2 (skill 0), and question 3 (skill 1) @@ -1266,7 +1299,10 @@ class QuestionAssessmentProgressControllerTest { // Question 1 // Submit question 1 wrong answer submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) viewHintForQuestion1(0) + submitIncorrectAnswerForQuestion1(2) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewHintForQuestion1(1) submitCorrectAnswerForQuestion1() @@ -1278,11 +1314,11 @@ class QuestionAssessmentProgressControllerTest { val userAssessmentPerformance = getExpectedGrade(TEST_SKILL_ID_LIST_01) val totalScore = FractionGrade.newBuilder().apply { - pointsReceived = 2.7 + pointsReceived = 2.5 totalPointsAvailable = 3.0 }.build() val skill0Score = FractionGrade.newBuilder().apply { - pointsReceived = 1.7 + pointsReceived = 1.5 totalPointsAvailable = 2.0 }.build() val skill1Score = FractionGrade.newBuilder().apply { @@ -1307,29 +1343,43 @@ class QuestionAssessmentProgressControllerTest { // Question 1 // Submit question 1 wrong answer submitIncorrectAnswerForQuestion1(2) - viewSolutionForQuestion1() + submitIncorrectAnswerForQuestion1(2) + viewHintForQuestion1(index = 0) + submitIncorrectAnswerForQuestion1(2) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) + viewHintForQuestion1(index = 1) submitCorrectAnswerForQuestion1() // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) + viewHintForQuestion2() + submitIncorrectAnswerForQuestion2(4.0) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion2() submitCorrectAnswerForQuestion2() // Question 3 // Submit question 3 wrong answer submitIncorrectAnswerForQuestion3("3/4") + submitIncorrectAnswerForQuestion3("3/4") + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) + ) + submitIncorrectAnswerForQuestion3("3/4") + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion3() submitCorrectAnswerForQuestion3() val userAssessmentPerformance = getExpectedGrade(TEST_SKILL_ID_LIST_01) - val skill0Mastery = -0.2 + val skill0Mastery = -0.19 val skill1Mastery = -0.1 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } @Test @@ -1353,9 +1403,9 @@ class QuestionAssessmentProgressControllerTest { val skill1Mastery = 0.1 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } @Test @@ -1374,23 +1424,30 @@ class QuestionAssessmentProgressControllerTest { // Question 2 // Submit question 2 wrong answer submitIncorrectAnswerForQuestion2(4.0) + submitIncorrectAnswerForQuestion2(4.0) viewHintForQuestion2() submitCorrectAnswerForQuestion2() // Question 3 // Submit question 3 wrong answer submitIncorrectAnswerForQuestion3("3/4") + submitIncorrectAnswerForQuestion3("3/4") + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) + ) + submitIncorrectAnswerForQuestion3("3/4") + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewSolutionForQuestion3() submitCorrectAnswerForQuestion3() val userAssessmentPerformance = getExpectedGrade(TEST_SKILL_ID_LIST_01) - val skill0Mastery = 0.03 + val skill0Mastery = -0.02 val skill1Mastery = -0.1 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } @Test @@ -1420,13 +1477,13 @@ class QuestionAssessmentProgressControllerTest { val skill1Mastery = -0.1 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } @Test - fun multipleHintsViewed_forQuestionWithWrongAnswer_returnMastery0Point11ForLinkedSkill() { + fun multipleHintsViewed_forQuestionWithWrongAnswer_returnMastery0Point01ForLinkedSkill() { setUpTestApplicationWithSeed(questionSeed = 0) subscribeToCurrentQuestionToAllowSessionToLoad() // This will generate question 1 (skill 0), question 2 (skill 0), and question 3 (skill 1) @@ -1435,7 +1492,10 @@ class QuestionAssessmentProgressControllerTest { // Question 1 // Submit question 1 wrong answer submitIncorrectAnswerForQuestion1(2) + submitIncorrectAnswerForQuestion1(2) viewHintForQuestion1(0) + submitIncorrectAnswerForQuestion1(2) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) viewHintForQuestion1(1) submitCorrectAnswerForQuestion1() @@ -1446,13 +1506,13 @@ class QuestionAssessmentProgressControllerTest { submitCorrectAnswerForQuestion3() val userAssessmentPerformance = getExpectedGrade(TEST_SKILL_ID_LIST_01) - val skill0Mastery = 0.11 + val skill0Mastery = 0.01 val skill1Mastery = 0.1 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } @Test @@ -1479,9 +1539,9 @@ class QuestionAssessmentProgressControllerTest { val skill1Mastery = 0.0 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } @Test @@ -1508,9 +1568,9 @@ class QuestionAssessmentProgressControllerTest { val skill1Mastery = 0.0 assertThat(userAssessmentPerformance.masteryPerSkillMappingCount).isEqualTo(2) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_0)) - .isEqualTo(skill0Mastery) + .isWithin(TOLERANCE).of(skill0Mastery) assertThat(userAssessmentPerformance.getMasteryPerSkillMappingOrThrow(TEST_SKILL_ID_1)) - .isEqualTo(skill1Mastery) + .isWithin(TOLERANCE).of(skill1Mastery) } private fun setUpTestApplicationWithSeed(questionSeed: Long) { @@ -1613,7 +1673,6 @@ class QuestionAssessmentProgressControllerTest { } private fun submitIncorrectAnswerForQuestion0(answer: String) { - assertThat(answer).isNotEqualTo("1/2") submitTextInputAnswerAndMoveToNextQuestion(answer) verify( mockCurrentQuestionLiveDataObserver, @@ -1626,7 +1685,6 @@ class QuestionAssessmentProgressControllerTest { } private fun submitIncorrectAnswerForQuestion1(answer: Int) { - assertThat(answer).isNotEqualTo(1) submitMultipleChoiceAnswerAndMoveToNextQuestion(answer) verify( mockCurrentQuestionLiveDataObserver, @@ -1642,15 +1700,8 @@ class QuestionAssessmentProgressControllerTest { } else if (index == 1) { assertThat(hint.hintContent.html).contains("

Second hint text will appear here

") } - questionAssessmentProgressController.submitHintIsRevealed( - ephemeralQuestion.ephemeralState.state, true, index - ) - } - - private fun viewSolutionForQuestion1() { - val ephemeralQuestion = currentQuestionResultCaptor.value.getOrThrow() - questionAssessmentProgressController.submitSolutionIsRevealed( - ephemeralQuestion.ephemeralState.state + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = index) ) } @@ -1659,7 +1710,6 @@ class QuestionAssessmentProgressControllerTest { } private fun submitIncorrectAnswerForQuestion2(answer: Double) { - assertThat(answer).isNotEqualTo(3.0) submitNumericInputAnswerAndMoveToNextQuestion(answer) verify( mockCurrentQuestionLiveDataObserver, @@ -1671,8 +1721,8 @@ class QuestionAssessmentProgressControllerTest { val ephemeralQuestion = currentQuestionResultCaptor.value.getOrThrow() val hint = ephemeralQuestion.ephemeralState.state.interaction.getHint(0) assertThat(hint.hintContent.html).contains("

Hint text will appear here

") - questionAssessmentProgressController.submitHintIsRevealed( - ephemeralQuestion.ephemeralState.state, true, 0 + verifyOperationSucceeds( + questionAssessmentProgressController.submitHintIsRevealed(hintIndex = 0) ) } @@ -1680,9 +1730,7 @@ class QuestionAssessmentProgressControllerTest { val ephemeralQuestion = currentQuestionResultCaptor.value.getOrThrow() val solution = ephemeralQuestion.ephemeralState.state.interaction.solution assertThat(solution.correctAnswer.correctAnswer).isEqualTo("3.0") - questionAssessmentProgressController.submitSolutionIsRevealed( - ephemeralQuestion.ephemeralState.state - ) + verifyOperationSucceeds(questionAssessmentProgressController.submitSolutionIsRevealed()) } private fun submitCorrectAnswerForQuestion3() { @@ -1690,7 +1738,6 @@ class QuestionAssessmentProgressControllerTest { } private fun submitIncorrectAnswerForQuestion3(answer: String) { - assertThat(answer).isNotEqualTo("1/2") submitTextInputAnswerAndMoveToNextQuestion(answer) verify( mockCurrentQuestionLiveDataObserver, @@ -1702,9 +1749,7 @@ class QuestionAssessmentProgressControllerTest { val ephemeralQuestion = currentQuestionResultCaptor.value.getOrThrow() val solution = ephemeralQuestion.ephemeralState.state.interaction.solution assertThat(solution.correctAnswer.correctAnswer).isEqualTo("1/2") - questionAssessmentProgressController.submitSolutionIsRevealed( - ephemeralQuestion.ephemeralState.state - ) + verifyOperationSucceeds(questionAssessmentProgressController.submitSolutionIsRevealed()) } private fun submitCorrectAnswerForQuestion4() { @@ -1715,6 +1760,13 @@ class QuestionAssessmentProgressControllerTest { submitNumericInputAnswerAndMoveToNextQuestion(5.0) } + private fun EphemeralState.isHintRevealed(hintIndex: Int): Boolean { + return pendingState.helpIndex.isHintRevealed(hintIndex, state.interaction.hintList) + } + + private fun EphemeralState.isSolutionRevealed(): Boolean = + pendingState.helpIndex.isSolutionRevealed() + private fun getExpectedGrade(skillIdList: List): UserAssessmentPerformance { subscribeToScoreAndMasteryCalculations(skillIdList) testCoroutineDispatchers.runCurrent() @@ -1725,6 +1777,25 @@ class QuestionAssessmentProgressControllerTest { return performanceCalculationCaptor.value.getOrThrow() } + /** + * Verifies that the specified live data provides at least one successful operation. This will + * change test-wide mock state, and synchronizes background execution. + */ + private fun verifyOperationSucceeds(liveData: LiveData>) { + reset(mockAsyncResultLiveDataObserver) + liveData.observeForever(mockAsyncResultLiveDataObserver) + testCoroutineDispatchers.runCurrent() + verify(mockAsyncResultLiveDataObserver).onChanged(asyncResultCaptor.capture()) + asyncResultCaptor.value.apply { + // This bit of conditional logic is used to add better error reporting when failures occur. + if (isFailure()) { + throw AssertionError("Operation failed", getErrorOrNull()) + } + assertThat(isSuccess()).isTrue() + } + reset(mockAsyncResultLiveDataObserver) + } + // TODO(#89): Move this to a common test application component. @Module class TestModule { @@ -1810,7 +1881,8 @@ class QuestionAssessmentProgressControllerTest { InteractionsModule::class, DragDropSortInputModule::class, TestLogReportingModule::class, ImageClickInputModule::class, LogStorageModule::class, TestDispatcherModule::class, RatioInputModule::class, RobolectricModule::class, FakeOppiaClockModule::class, - CachingTestModule::class, NetworkConnectionUtilDebugModule::class + CachingTestModule::class, HintsAndSolutionConfigModule::class, + HintsAndSolutionProdModule::class, NetworkConnectionUtilDebugModule::class ] ) interface TestApplicationComponent : DataProvidersInjector { diff --git a/domain/src/test/java/org/oppia/android/domain/question/QuestionTrainingControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/question/QuestionTrainingControllerTest.kt index 150f28fc65a..e243d66b9e7 100644 --- a/domain/src/test/java/org/oppia/android/domain/question/QuestionTrainingControllerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/question/QuestionTrainingControllerTest.kt @@ -32,6 +32,8 @@ import org.oppia.android.domain.classify.rules.numberwithunits.NumberWithUnitsRu import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModule import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule import org.oppia.android.domain.oppialogger.LogStorageModule import org.oppia.android.domain.topic.TEST_QUESTION_ID_0 import org.oppia.android.domain.topic.TEST_QUESTION_ID_1 @@ -333,6 +335,7 @@ class QuestionTrainingControllerTest { TestQuestionModule::class, TestLogReportingModule::class, ImageClickInputModule::class, LogStorageModule::class, TestDispatcherModule::class, RatioInputModule::class, RobolectricModule::class, FakeOppiaClockModule::class, CachingTestModule::class, + HintsAndSolutionConfigModule::class, HintsAndSolutionProdModule::class, NetworkConnectionUtilDebugModule::class ] ) diff --git a/model/src/main/proto/exploration.proto b/model/src/main/proto/exploration.proto index cc911ded54f..41ec39f1843 100644 --- a/model/src/main/proto/exploration.proto +++ b/model/src/main/proto/exploration.proto @@ -54,14 +54,17 @@ enum ObjectType { message State { // The name of the State. string name = 1; + // Mapping from content_id to a VoiceoverMapping map recorded_voiceovers = 2; SubtitledHtml content = 3; + // Mapping from content_id to a TranslationMapping map written_translations = 4; repeated ParamChange param_changes = 5; string classifier_model_id = 6; Interaction interaction = 7; + // Boolean indicating whether the creator wants to ask for answer details // from the learner about why they picked a particular answer while // playing the exploration. @@ -71,6 +74,7 @@ message State { // Structure for customization args for ParamChange objects. message ParamChangeCustomizationArgs { bool parse_with_jinja = 1; + // If the param change has only a single value, we will populate just // one element in this list repeated string list_of_values = 3; @@ -85,6 +89,7 @@ message Interaction { reserved 4; repeated Hint hint = 5; Outcome default_outcome = 6; + // Mapping from the name of a customization arg to the default interaction // object of the customization arg map customization_args = 7; @@ -138,6 +143,7 @@ message AnswerGroup { message Misconception { // Skill ID parsed from the misconception. string skill_id = 1; + // Misconception ID parsed from the misconception. string misconception_id = 2; } @@ -154,12 +160,16 @@ message Solution { string interaction_id = 1; // Flag that is true if correct_answer is the only correct answer of the question. bool answer_is_exclusive = 2; + // correct_answer of the State. CorrectAnswer correct_answer = 3; + // Core explanation to the correct answer. SubtitledHtml explanation = 4; - // To check if the solution was revealed or not by the learner. - bool solution_is_revealed = 5; + + // Whether the solution was revealed (deprecated). This information is now available through the + // HelpIndex message passed with EphemeralState. + reserved 5; } // Structure for a Correct answer in Solution @@ -177,8 +187,11 @@ message CorrectAnswer { message Hint { // Hint data. SubtitledHtml hint_content = 1; - // To check if the hint was revealed or not - bool hint_is_revealed = 2; + + // Whether the hint was revealed (deprecated). This information is now available through + // the HelpIndex message passed through EphemeralState. + reserved 2; + // The current state that is display to the user. State state = 3; } @@ -243,12 +256,19 @@ message PendingState { // A list of previous wrong answers that led back to this state, and Oppia's responses. These responses are in the // order the learner submitted them. repeated AnswerAndResponse wrong_answer = 1; - // A list of hints. - repeated Hint hint = 2; + + // A list of hints (deprecated). To get the list of hints, retrieve them from the State message + // stored within the top-level EphemeralState & cross reference it with the HelpIndex provided + // below to get information about the current state of hints/solution. + reserved 2; + + // The help index for the current exploration. + HelpIndex help_index = 3; } // Corresponds to an exploration state that the learner has previous completed. message CompletedState { + // The list of answers and responses that were used to finish this state. These answers are in the order that the // The list of answers and responses that were used to finish this state. These answers are in the order that the // learner submitted them, so the last answer is guaranteed to be the correct answer. repeated AnswerAndResponse answer = 1; @@ -258,6 +278,7 @@ message CompletedState { message UserAnswer { // The submitted answer. InteractionObject answer = 1; + // A user-friendly textual representation of the answer. oneof textual_answer { // An HTML textual representation of the answer. @@ -267,6 +288,7 @@ message UserAnswer { // A list of HTML textual representation of the answer. ListOfSetsOfHtmlStrings list_of_html_answers = 4; } + // An accessible version of the corresponding plain answer. It will be used to read out the // answer when there is a screen-reader enabled. Also when this is value is not initialized and // if the screen-reader is enabled in that case the plain answer/html answer would be read out. @@ -314,18 +336,35 @@ message AnswerOutcome { // A structure corresponding to the index of a hint or solution in a state. This structure is set up // to properly account for variable numbers of hints, for cases when only a solution or no solution -// exists, and for when there are no hints or solutions. +// exists, and for when there are no hints or solutions. This structure represents the entire state +// needed to determine which hints can be shown, have been seen, whether the solution can be shown, +// and whether the solution has been seen. message HelpIndex { + // Deprecated hint index. This is now available via the two hint index fields below (which provide + // additional context on whether the hint has been revealed). + reserved 1; + // This type is uninitialized in cases when no index is currently available (either because a hint // or solution hasn't yet been triggered, or because there are none to trigger). oneof index_type { - // Indicates this help index corresponds to the index of a hint within the hint list of a state. - int32 hint_index = 1; - // Indicates this help index corresponds to the solution of a state. The boolean value here has // no importance and is always 'true'. bool show_solution = 2; + // Indicates this help index corresponds to the index of the next available hint within the hint + // list of a state (meaning the index corresponding to this value is the next hint that may be + // revealed by the user). This state assumes all prior hints (if any) have already been + // revealed. + int32 next_available_hint_index = 4; + + // Indicates this help index corresponds to the index of the last revealed hint within the hint + // list of a state (meaning the index corresponding to this value is the latest hint that's been + // revealed by the user). This state assumes all prior hints (if any) have also already been + // revealed. Note that this could correspond to the last hint available to view and, in that + // case, the solution should not yet be available to reveal until it is also unlocked (at which + // point the state show_solution should be used, instead). + int32 latest_revealed_hint_index = 5; + // Indicates that everything available has been revealed. Note that this is different than the // case when there are no hints or solutions to trigger, even though the resulting behavior may // be different. This case specifically indicates that all hints and the solution, if present, diff --git a/model/src/main/proto/exploration_checkpoint.proto b/model/src/main/proto/exploration_checkpoint.proto index 6756fac3428..a01dc87cea5 100644 --- a/model/src/main/proto/exploration_checkpoint.proto +++ b/model/src/main/proto/exploration_checkpoint.proto @@ -30,13 +30,13 @@ message ExplorationCheckpoint { // The index of the current selected state from the deck of states. int32 state_index = 4; - // Stores -1 if no hint for the pending top state has been revealed otherwise it stores the index - // of the hint that the learner has revealed. - int32 hint_index = 5; + // The last revealed hint index (deprecated). This has been functionally replaced by the HelpIndex + // provided below. + reserved 5; - // Stores true if the solution to the pending top state has been revealed by the learner otherwise - // it stores false. - bool solution_is_revealed = 6; + // Whether the solution was revealed (deprecated). This has been functionally replaced by the + // HelpIndex provided below. + reserved 6; // The title of the exploration whose checkpoint is saved. string exploration_title = 7; @@ -46,6 +46,9 @@ message ExplorationCheckpoint { // The timestamp in milliseconds of when the checkpoint was saved for the first time. int64 timestamp_of_first_checkpoint = 9; + + // The saved help index for the exploration. + HelpIndex help_index = 10; } // Corresponds to exploration states that have been completed. diff --git a/scripts/assets/kdoc_validity_exemptions.textproto b/scripts/assets/kdoc_validity_exemptions.textproto index 7ea1f740ff5..3c271b9dfd1 100644 --- a/scripts/assets/kdoc_validity_exemptions.textproto +++ b/scripts/assets/kdoc_validity_exemptions.textproto @@ -376,7 +376,6 @@ exempted_file_path: "domain/src/main/java/org/oppia/android/domain/classify/rule exempted_file_path: "domain/src/main/java/org/oppia/android/domain/classify/rules/InteractionObjectTypeExtractorRepository.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/classify/rules/continueinteraction/ContinueModule.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgress.kt" -exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/lightweightcheckpointing/ExplorationCheckpointController.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/lightweightcheckpointing/ExplorationStorageModule.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/oppialogger/LogStorageModule.kt" @@ -387,7 +386,6 @@ exempted_file_path: "domain/src/main/java/org/oppia/android/domain/question/Ques exempted_file_path: "domain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/question/QuestionConstantsProvider.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/question/QuestionTrainingConstantsProvider.kt" -exempted_file_path: "domain/src/main/java/org/oppia/android/domain/state/StateDeck.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/topic/StoryProgressController.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/topic/TopicController.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/topic/TopicListController.kt" diff --git a/scripts/assets/test_file_exemptions.textproto b/scripts/assets/test_file_exemptions.textproto index 930b68c7f9f..0721b775210 100644 --- a/scripts/assets/test_file_exemptions.textproto +++ b/scripts/assets/test_file_exemptions.textproto @@ -245,11 +245,6 @@ exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/StateP exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/StateViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/answerhandling/InteractionAnswerErrorOrAvailabilityCheckReceiver.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/answerhandling/InteractionAnswerHandler.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowAdditionalHintsMillis.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/DelayShowInitialHintMillis.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/hintsandsolution/HintsAndSolutionConfigModule.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContinueInteractionViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContinueNavigationButtonViewModel.kt" @@ -552,6 +547,12 @@ exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/E exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/ExplorationRetriever.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/exploration/lightweightcheckpointing/ExplorationCheckpointState.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/feedbackreporting/FeedbackReportingModule.kt" +exempted_file_path: "domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsFromWrongAnswerMillis.kt" +exempted_file_path: "domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowAdditionalHintsMillis.kt" +exempted_file_path: "domain/src/main/java/org/oppia/android/domain/hintsandsolution/DelayShowInitialHintMillis.kt" +exempted_file_path: "domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigFastShowTestModule.kt" +exempted_file_path: "domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionConfigModule.kt" +exempted_file_path: "domain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandler.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/onboarding/ExpirationMetaDataRetriever.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/onboarding/ExpirationMetaDataRetrieverImpl.kt" exempted_file_path: "domain/src/main/java/org/oppia/android/domain/onboarding/ExpirationMetaDataRetrieverModule.kt" diff --git a/testing/BUILD.bazel b/testing/BUILD.bazel index b89328a0e90..97438b9bbe4 100644 --- a/testing/BUILD.bazel +++ b/testing/BUILD.bazel @@ -88,7 +88,9 @@ TEST_DEPS = [ "//third_party:org_jetbrains_kotlinx_kotlinx-coroutines-test", "//third_party:org_mockito_mockito-core", "//third_party:robolectric_android-all", - "//utility/src/main/java/org/oppia/android/util/logging:logger_module", + "//utility/src/main/java/org/oppia/android/util/caching/testing:caching_test_module", + "//utility/src/main/java/org/oppia/android/util/logging:prod_module", + "//utility/src/main/java/org/oppia/android/util/networking:debug_module", ] # Qualified file paths for test classes that have been migrated over to their own packages & @@ -116,4 +118,10 @@ kt_android_library( ], ) +filegroup( + name = "test_manifest", + srcs = ["src/test/AndroidManifest.xml"], + visibility = ["//:oppia_testing_visibility"], +) + dagger_rules() diff --git a/testing/src/test/BUILD.bazel b/testing/src/test/BUILD.bazel deleted file mode 100644 index 96475bc8ae3..00000000000 --- a/testing/src/test/BUILD.bazel +++ /dev/null @@ -1,10 +0,0 @@ -# TODO(#1532): Rename file to 'BUILD' post-Gradle. -""" -Top-level testing module files & targets. -""" - -filegroup( - name = "test_manifest", - srcs = ["AndroidManifest.xml"], - visibility = ["//:oppia_testing_visibility"], -) diff --git a/testing/src/test/java/org/oppia/android/testing/networking/BUILD.bazel b/testing/src/test/java/org/oppia/android/testing/networking/BUILD.bazel index 747bd68be5e..99403b6dee1 100644 --- a/testing/src/test/java/org/oppia/android/testing/networking/BUILD.bazel +++ b/testing/src/test/java/org/oppia/android/testing/networking/BUILD.bazel @@ -10,7 +10,7 @@ oppia_android_test( srcs = ["NetworkConnectionTestUtilTest.kt"], custom_package = "org.oppia.android.testing.networking", test_class = "org.oppia.android.testing.networking.NetworkConnectionTestUtilTest", - test_manifest = "//testing/src/test:test_manifest", + test_manifest = "//testing:test_manifest", deps = [ ":dagger", "//testing/src/main/java/org/oppia/android/testing/networking:network_connection_test_util", diff --git a/testing/src/test/java/org/oppia/android/testing/threading/BUILD.bazel b/testing/src/test/java/org/oppia/android/testing/threading/BUILD.bazel index e26fe1b626e..08c073d5e32 100644 --- a/testing/src/test/java/org/oppia/android/testing/threading/BUILD.bazel +++ b/testing/src/test/java/org/oppia/android/testing/threading/BUILD.bazel @@ -24,7 +24,7 @@ oppia_android_test( srcs = ["CoroutineExecutorServiceTest.kt"], custom_package = "org.oppia.android.data.testing", test_class = "org.oppia.android.testing.threading.CoroutineExecutorServiceTest", - test_manifest = "//testing/src/test:test_manifest", + test_manifest = "//testing:test_manifest", deps = [ ":dagger", "//testing", @@ -41,7 +41,7 @@ oppia_android_test( srcs = ["TestCoroutineDispatcherEspressoImplTest.kt"], custom_package = "org.oppia.android.data.testing", test_class = "org.oppia.android.testing.threading.TestCoroutineDispatcherEspressoImplTest", - test_manifest = "//testing/src/test:test_manifest", + test_manifest = "//testing:test_manifest", deps = [ ":dagger", ":test_coroutine_dispatcher_test_base", @@ -57,7 +57,7 @@ oppia_android_test( srcs = ["TestCoroutineDispatcherRobolectricImplTest.kt"], custom_package = "org.oppia.android.data.testing", test_class = "org.oppia.android.testing.threading.TestCoroutineDispatcherRobolectricImplTest", - test_manifest = "//testing/src/test:test_manifest", + test_manifest = "//testing:test_manifest", deps = [ ":dagger", ":test_coroutine_dispatcher_test_base", @@ -73,7 +73,7 @@ oppia_android_test( srcs = ["TestCoroutineDispatcherTest.kt"], custom_package = "org.oppia.android.data.testing", test_class = "org.oppia.android.testing.threading.TestCoroutineDispatcherTest", - test_manifest = "//testing/src/test:test_manifest", + test_manifest = "//testing:test_manifest", deps = [ ":dagger", "//testing", diff --git a/third_party/maven_install.json b/third_party/maven_install.json index 03eef8ecc76..3886ce482d9 100644 --- a/third_party/maven_install.json +++ b/third_party/maven_install.json @@ -1,8 +1,8 @@ { "dependency_tree": { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": 171679321, - "__RESOLVED_ARTIFACTS_HASH": -2135931254, + "__INPUT_ARTIFACTS_HASH": -1770608701, + "__RESOLVED_ARTIFACTS_HASH": -348454682, "conflict_resolution": { "androidx.appcompat:appcompat:1.0.2": "androidx.appcompat:appcompat:1.2.0", "androidx.core:core:1.0.1": "androidx.core:core:1.3.0", @@ -6290,6 +6290,66 @@ "sha256": "f44739e95d21ca352aff947086d3176e8c61cf91ccbc100cf335d0964de44fe0", "url": "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-lite/3.0.0/protobuf-lite-3.0.0.jar" }, + { + "coord": "com.google.truth.extensions:truth-liteproto-extension:0.43", + "dependencies": [ + "com.google.guava:guava:28.1-android", + "com.google.auto.value:auto-value-annotations:1.6.5", + "junit:junit:4.12", + "org.hamcrest:hamcrest-core:1.3", + "com.google.truth:truth:0.43", + "com.googlecode.java-diff-utils:diffutils:1.3.0", + "com.google.errorprone:error_prone_annotations:2.3.2", + "org.checkerframework:checker-compat-qual:2.5.5" + ], + "directDependencies": [ + "com.google.guava:guava:28.1-android", + "com.google.auto.value:auto-value-annotations:1.6.5", + "com.google.truth:truth:0.43", + "com.google.errorprone:error_prone_annotations:2.3.2", + "org.checkerframework:checker-compat-qual:2.5.5" + ], + "file": "v1/https/repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar", + "mirror_urls": [ + "https://maven.google.com/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar", + "https://repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar", + "https://maven.fabric.io/public/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar", + "https://maven.google.com/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar", + "https://repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar" + ], + "sha256": "30cc23160edb203e82cccfc429839f056fb79c426b9e0234575f929561cc8e71", + "url": "https://repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43.jar" + }, + { + "coord": "com.google.truth.extensions:truth-liteproto-extension:jar:sources:0.43", + "dependencies": [ + "com.googlecode.java-diff-utils:diffutils:jar:sources:1.3.0", + "org.hamcrest:hamcrest-core:jar:sources:1.3", + "com.google.auto.value:auto-value-annotations:jar:sources:1.6.5", + "com.google.truth:truth:jar:sources:0.43", + "org.checkerframework:checker-compat-qual:jar:sources:2.5.5", + "com.google.guava:guava:jar:sources:28.1-android", + "junit:junit:jar:sources:4.12", + "com.google.errorprone:error_prone_annotations:jar:sources:2.3.2" + ], + "directDependencies": [ + "com.google.auto.value:auto-value-annotations:jar:sources:1.6.5", + "com.google.truth:truth:jar:sources:0.43", + "org.checkerframework:checker-compat-qual:jar:sources:2.5.5", + "com.google.guava:guava:jar:sources:28.1-android", + "com.google.errorprone:error_prone_annotations:jar:sources:2.3.2" + ], + "file": "v1/https/repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar", + "mirror_urls": [ + "https://maven.google.com/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar", + "https://repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar", + "https://maven.fabric.io/public/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar", + "https://maven.google.com/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar", + "https://repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar" + ], + "sha256": "c98e475ab4b321d60407ed5ebfa3a2107c23c8bf89c61c66d17d9a72e04fa8e7", + "url": "https://repo1.maven.org/maven2/com/google/truth/extensions/truth-liteproto-extension/0.43/truth-liteproto-extension-0.43-sources.jar" + }, { "coord": "com.google.truth:truth:0.43", "dependencies": [ diff --git a/third_party/versions.bzl b/third_party/versions.bzl index 54c923de498..2d94cf461a0 100644 --- a/third_party/versions.bzl +++ b/third_party/versions.bzl @@ -91,6 +91,7 @@ MAVEN_TEST_DEPENDENCY_VERSIONS = { "androidx.work:work-testing": "2.4.0", "com.github.bumptech.glide:mocks": "4.11.0", "com.google.protobuf:protobuf-java": "3.17.3", + "com.google.truth.extensions:truth-liteproto-extension": "0.43", "com.google.truth:truth": "0.43", "com.squareup.okhttp3:mockwebserver": "4.1.0", "com.squareup.retrofit2:retrofit-mock": "2.5.0",