Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
280 lines (248 sloc) 11.2 KB
package com.github.johnnysc.tutor.presentation.chat
import android.app.Application
import android.os.Bundle
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import com.github.johnnysc.tutor.R
import com.github.johnnysc.tutor.data.ChatBotCommands
import com.github.johnnysc.tutor.data.ChatBotMessages
import com.github.johnnysc.tutor.data.LearningPair
import com.github.johnnysc.tutor.data.Repository
import com.github.johnnysc.tutor.presentation.core.Navigator
import com.github.johnnysc.tutor.presentation.study.STUDY_RESULTS
import com.github.johnnysc.tutor.presentation.study.StudyResults
const val SAVED_POSITION = "SAVED_POSITION"
const val SAVED_CHAT_CONTEXT = "SAVED_CHAT_CONTEXT"
/**
* @author Asatryan on 22.06.19
*/
class ChatViewModel(private val app: Application) : AndroidViewModel(app) {
private companion object ChatContext {
const val INITIAL = 0
const val CATEGORIES = 1
const val CATEGORY = 2
const val STUDY = 3
}
var messageState = MutableLiveData<ChatMessage>()
var navigateState = MutableLiveData<Navigator.Screen>()
private var chatContext: Int = INITIAL
private var studyItemPosition: Int = 0
fun init(savedInstanceState: Bundle?) {
if (savedInstanceState == null) {
messageState.value = BotMessage(app.getString(ChatBotMessages.INITIAL, ChatBotCommands.HELP))
} else {
studyItemPosition = savedInstanceState.getInt(SAVED_POSITION)
chatContext = savedInstanceState.getInt(SAVED_CHAT_CONTEXT)
Repository.updateStudyResults(savedInstanceState.getSerializable(STUDY_RESULTS) as StudyResults)
}
}
fun handleUserInput(text: String) {
if (text.trim().isNotEmpty()) {
messageState.value = UserMessage(text)
answerOn(text.trim())
}
}
fun saveState(outState: Bundle) {
outState.putInt(SAVED_POSITION, studyItemPosition)
outState.putInt(SAVED_CHAT_CONTEXT, chatContext)
outState.putSerializable(STUDY_RESULTS, Repository.getCurrentStudyResults())
}
//region private funs
private fun answerOn(userInput: String) {
when (chatContext) {
INITIAL -> handleUserInputInInitialContext(userInput)
CATEGORIES -> handleUserInputInCategoriesContext(userInput)
CATEGORY -> handleUserInputInCategoryContext(userInput)
STUDY -> handleUserInputInCategoryStudy(userInput)
}
}
private fun handleUserInputInInitialContext(userInput: String) {
when (userInput.toLowerCase()) {
ChatBotCommands.HELP -> messageState.value = BotMessage(
app.getString(ChatBotMessages.HELP, getInitialCommandsWithDescriptions())
)
ChatBotCommands.CATEGORIES -> {
chatContext = CATEGORIES
showAllCategoriesData()
}
else -> showNothingFoundMessage()
}
}
private fun handleUserInputInCategoriesContext(userInput: String) {
when (userInput.toLowerCase()) {
ChatBotCommands.HELP -> messageState.value = BotMessage(
app.getString(ChatBotMessages.HELP, getCategoryContextActions())
)
else -> handleInputAfterCategoryCommand(userInput)
}
}
private fun handleUserInputInCategoryContext(userInput: String) {
when (userInput.toLowerCase()) {
ChatBotCommands.CATEGORY_DETAILS -> formDetailsForAlreadyChosenCategory()
ChatBotCommands.STUDY -> startStudy()
else -> handleUserInputInCategoriesContext(userInput)
}
}
private fun handleUserInputInCategoryStudy(translation: String) {
if (translation.trim().equals(ChatBotCommands.SKIP, true)) {
val correctTranslation = Repository.getLearningPairByPosition(studyItemPosition).translation
messageState.value =
BotMessage(app.getString(ChatBotMessages.SHOW_CORRECT_WHEN_SKIPPED, correctTranslation))
Repository.incrementIncorrectsCount(studyItemPosition)
handleNextSource()
} else if (translation.trim().isNotEmpty()) {
val pair = Repository.getLearningPairByPosition(studyItemPosition)
if (pair.translation.equals(translation.trim(), true)) {
Repository.incrementCorrectsCount(studyItemPosition)
messageState.value = BotMessage(app.getString(R.string.correct_translation_message))
handleNextSource()
} else {
Repository.incrementIncorrectsCount(studyItemPosition)
messageState.value = BotMessage(app.getString(R.string.incorrect_translation_message))
showLearningPairSource()
}
}
}
private fun handleNextSource() {
studyItemPosition++
if (Repository.isPairLastOne(studyItemPosition)) {
val it = Repository.getCurrentStudyResults()
messageState.value =
BotMessage(app.getString(R.string.study_results_stats, it.corrects, it.total))
chatContext = CATEGORIES
showAllCategoriesData()
} else {
showLearningPairSource()
}
}
private fun showNothingFoundMessage() {
messageState.value =
BotMessage(app.getString(ChatBotMessages.NO_MATCHES, ChatBotCommands.HELP))
}
private fun showAllCategoriesData() {
val categories = Repository.getCategoryDataList()
if (categories.isEmpty())
messageState.value = BotMessage(app.getString(R.string.no_category_message))
else {
messageState.value = BotMessage(app.getString(ChatBotMessages.CATEGORIES))
categories.forEachIndexed { index, it ->
val text = index.toString() + ".\nname: " + it.name + "\nitems count: " + it.pairsCount
messageState.value = BotMessage(text)
}
messageState.value = BotMessage(getCategoryContextActions())
}
}
private fun getCategoryContextActions(): String {
var text = app.getString(ChatBotMessages.GOTO, ChatBotCommands.GOTO, ChatBotCommands.GOTO)
text += "\n\n" + app.getString(
ChatBotMessages.SIMPLE_SHOW_CATEGORY,
ChatBotCommands.SIMPLE_SHOW_CATEGORY,
ChatBotCommands.SIMPLE_SHOW_CATEGORY
)
text += "\n\n" + app.getString(
ChatBotMessages.STUDY_FROM_CATEGORY,
ChatBotCommands.STUDY,
ChatBotCommands.STUDY
)
return text
}
private fun getInitialCommandsWithDescriptions(): String {
var text = "\n"
text += ChatBotCommands.CATEGORIES + " -> get categories data \n"
text += ChatBotCommands.HELP + " -> get help"
return text
}
private fun handleInputAfterCategoryCommand(userInput: String) {
when {
userInput.toLowerCase().startsWith(ChatBotCommands.GOTO) -> try {
val categoryPosition = Integer.parseInt(userInput.substring(ChatBotCommands.GOTO.length))
val categoryName = Repository.getCategoryDataList()[categoryPosition].name
Repository.saveChosenCategoryName(categoryName)
navigateState.value = Navigator.Screen.PAIR_LIST
} catch (e: Exception) {
chatContext = INITIAL
handleUserInputInInitialContext(userInput)
}
userInput.toLowerCase().startsWith(ChatBotCommands.SIMPLE_SHOW_CATEGORY) -> try {
val categoryPosition =
Integer.parseInt(userInput.substring(ChatBotCommands.SIMPLE_SHOW_CATEGORY.length))
val categoryName = Repository.getCategoryDataList()[categoryPosition].name
Repository.saveChosenCategoryName(categoryName)
val learningPairs = Repository.getLearningPairList()
if (learningPairs.isNullOrEmpty()) {
messageState.value = BotMessage(app.getString(R.string.chat_bot_no_items_in_category))
} else {
chatContext = CATEGORY
showSimpleDetails(categoryName, learningPairs)
}
} catch (e: Exception) {
chatContext = INITIAL
handleUserInputInInitialContext(userInput)
}
userInput.toLowerCase().startsWith(ChatBotCommands.STUDY) -> try {
val categoryPosition =
Integer.parseInt(userInput.substring(ChatBotCommands.STUDY.length))
val categoryName = Repository.getCategoryDataList()[categoryPosition].name
Repository.saveChosenCategoryName(categoryName)
val learningPairs = Repository.getLearningPairList()
if (learningPairs.isNullOrEmpty()) {
messageState.value = BotMessage(app.getString(R.string.chat_bot_no_items_in_category))
} else {
startStudy()
}
} catch (e: Exception) {
chatContext = INITIAL
handleUserInputInInitialContext(userInput)
}
else -> {
chatContext = INITIAL
handleUserInputInInitialContext(userInput)
}
}
}
private fun showSimpleDetails(categoryName: String, pairs: List<LearningPair>) {
var text = "category: $categoryName \nlearning pairs:"
messageState.value = BotMessage(text)
pairs.forEach {
messageState.value = BotMessage(it.source)
}
text = app.getString(ChatBotMessages.SHOW_DETAILS, ChatBotCommands.CATEGORY_DETAILS)
text += "\n" + app.getString(ChatBotMessages.STUDY, ChatBotCommands.STUDY)
messageState.value = BotMessage(text)
}
private fun formDetailsForAlreadyChosenCategory() {
val learningPairs = Repository.getLearningPairList()
if (learningPairs.isNullOrEmpty()) {
messageState.value = BotMessage(app.getString(R.string.chat_bot_no_items_in_category))
} else {
showFullDetails(learningPairs)
}
}
private fun showFullDetails(learningPairs: List<LearningPair>) {
var text = "category: ${Repository.getChosenCategoryName()}\nlearning pairs:"
messageState.value = BotMessage(text)
learningPairs.forEach {
text = it.source + "\n" + it.translation + "\n\nCorrects' count: " + it.correctAnswersCount.toString() +
"\n" + "Incorrects' count: " + it.incorrectAnswersCount.toString()
messageState.value = BotMessage(text)
}
text = app.getString(ChatBotMessages.STUDY, ChatBotCommands.STUDY)
messageState.value = BotMessage(text)
}
private fun startStudy() {
chatContext = STUDY
studyItemPosition = 0
Repository.initStudyResults()
showLearningPairSource()
}
private fun showLearningPairSource() {
val pair = Repository.getLearningPairByPosition(studyItemPosition)
messageState.value = BotMessage(makeRequestMessage(pair.source))
}
private fun makeRequestMessage(source: String): String {
var text = app.getString(ChatBotMessages.INPUT_TRANSLATION, source)
text += "\n" + app.getString(ChatBotMessages.SKIP, ChatBotCommands.SKIP)
return text
}
//endregion
}
You can’t perform that action at this time.