diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 83978ee..05199cb 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -4,6 +4,8 @@ import kotlin.system.exitProcess import org.jetbrains.letsPlot.* import org.jetbrains.letsPlot.geom.geomBar import org.jetbrains.letsPlot.intern.Plot +import kotlin.reflect.KType +import kotlin.reflect.typeOf val scanner = Scanner(System.`in`) @@ -18,31 +20,26 @@ object StatisticBuilder { val wordsCountsMap = text.getSentencesList().map { counter++ to it.getWordsCount() } println("Print \"console\" if you have see data in console, \"graphic\" if you have see histogram and \"both\" if you have see them together:") - whenStatShowCycle@ while (true) { - when (readln()) { - "console" -> printStatisticsInConsole(text.getName(), wordsCountsMap.toMap()) - "graphic" -> buildGraphic(text.getName(), wordsCountsMap.toMap()) - "both" -> { - buildGraphic(text.getName(), wordsCountsMap.toMap()) - printStatisticsInConsole(text.getName(), wordsCountsMap.toMap()) - } - "return" -> return - else -> { - println("Repeat input or enter \"return\" to return in main menu") - continue@whenStatShowCycle - } + val request = Main.requestInput(listOf("console", "graphic", "both")) + request.first.exe() + + when (request.second) { + "console" -> printStatisticsInConsole(text.getName(), wordsCountsMap.toMap()) + "graphic" -> buildGraphic(text.getName(), wordsCountsMap.toMap()) + "both" -> { + buildGraphic(text.getName(), wordsCountsMap.toMap()) + printStatisticsInConsole(text.getName(), wordsCountsMap.toMap()) } - break@whenStatShowCycle } + } private fun buildGraphic(textName: String, mapOfSentenceNumToItsSize: Map) { val plot: Plot = ggplot(mapOfSentenceNumToItsSize) + ggsize(1000, 600) + geomBar { x = "sentence number"; y = "words count" } - } private fun printStatisticsInConsole(textName: String, mapOfSentenceNumToItsSize: Map) { @@ -51,48 +48,35 @@ object StatisticBuilder { println("-".repeat(textName.length)) println( "Statistics[num of sentence: count of words in it]: ${ - mapOfSentenceNumToItsSize.toList().joinToString("; ") { "${it.first}: ${it.second}" } }.") + mapOfSentenceNumToItsSize.toList().joinToString("; ") { "${it.first}: ${it.second}" } + }.") println("-".repeat(textName.length)) println("Done!\n") } private fun getTextData(): TextData.Text? { - println("Input name of text which you have to get statistics about:") println("Saved texts: ${TextData.getTextsNamesInString()}") - cycleSearchText@ while (true) { - return when (val name = readln().trim()) { - in TextData.getTextsNamesList() -> { - TextData.getTextByName(name)!! - } - - "return" -> null - else -> { - println("No text with name $name. Repeat input or enter return to return in main menu.") - continue@cycleSearchText - } - } - } + val nameRequest = Main.requestInput(TextData.getTextsNamesList()) + nameRequest.first.exe() + return TextData.getTextByName(nameRequest.second.toString()) } - } - object TextReader { fun askAndExecuteSelfCommands() { - println("Where do you want to add the text: from the console of a file?") - when (readln().lowercase()) { + println("Where do you want to add the text: from the console or a file?") + + val kindOfSource = Main.requestInput(listOf("console", "file")) + kindOfSource.first.exe() + + when (kindOfSource.second) { "console" -> readFromConsole() "file" -> readFromFile() - "return" -> return - else -> { - println("Repeat input or print \"return\" to return in main menu:") - askAndExecuteSelfCommands() - } } } @@ -128,38 +112,33 @@ object TextReader { val name = readln() val contentsFile: File + pathReadCycle@ while (true) { - println("Input a path to file:") - val filePath = readln() + val pathRequest = Main.requestInput() + pathRequest.first.exe() + val filePath = pathRequest.second.toString() + val testFile = File(filePath) - when { - filePath == "return" -> return - !testFile.exists() -> { - println("File path incorrect. Repeat input or enter \"return\" to return in main menu:") - continue@pathReadCycle - } - - else -> { - contentsFile = testFile - break@pathReadCycle - } + if (!testFile.exists()) { + println("Incorrect path. Repeat the input:") + continue@pathReadCycle + } else { + contentsFile = testFile + break@pathReadCycle } } + val content = contentsFile.readText() - correctInputQuestion@ while (true) { - print("Input was correct?[yes, no]: ") - when (readln()) { - "yes" -> addTextToData(name, content) - "no" -> readFromFile() - "return" -> return - else -> { - println("Input only \"yes\" or \"no\" or \"return\" if you want to exit in main menu:") - } - } - } + print("Input was correct?[yes, no]: ") + val correctInputRequest = Main.requestInput(listOf("yes", "no")) + correctInputRequest.first.exe() + when (correctInputRequest.second) { + "yes" -> addTextToData(name, content) + "no" -> readFromFile() + } } private fun addTextToData(textName: String, content: String) { @@ -222,11 +201,10 @@ object TextData { ) { fun getSentencesCount() = sentencesCount + fun getName() = name - fun getSentencesList(): List { - return sentencesList - } + fun getSentencesList() = sentencesList data class Sentence(private val wordsCount: Int) { fun getWordsCount() = wordsCount @@ -236,14 +214,15 @@ object TextData { } +fun exit(): Nothing { + println("bye!") + exitProcess(0) +} object CommandCenter { private enum class Commands(val executingFun: () -> Unit) { - EXIT({ - println("bye!") - exitProcess(0) - }), + EXIT(::exit), ADD_TEXT({ TextReader.askAndExecuteSelfCommands() }), SHOW_STATISTICS({ StatisticBuilder.askAndExecuteSelfCommands() }), REMOVE_TEXT({ println("remove") }) @@ -261,8 +240,85 @@ object CommandCenter { } -fun main() { - mainCycle@ while (true) { - (CommandCenter.readCommandFromConsole())() +interface InputOutcomeCommand { + val exe: () -> Unit +} + +object ContinueCommand : InputOutcomeCommand { + override val exe: () -> Unit = {} +} + +object ReturnCommand : InputOutcomeCommand { + override val exe: () -> Unit = { Main.work() } +} + + +class InvalidInputTypeException(expectedType: String) : Exception(expectedType) { + override val message: String = expectedType + get() = "Was expected type: $field, but it's impossible to convert input in it." + +} + +class InvalidElemInInputException() : Exception() + + +object Main { + + fun work() { + mainCycle@ while (true) { + (CommandCenter.readCommandFromConsole())() + } } + + inline fun requestInput(availableInputs: List? = null): Pair { + + var inputT: Any + + readingAndChangingTypeCycle@ while (true) { + + val input = readln() + if (input == "return") return Pair(ReturnCommand, "") + + try { + inputT = when (typeOf()) { + typeOf() -> input.toInt() + typeOf() -> input.toDouble() + typeOf() -> input.toBoolean() + typeOf() -> input.toByte() + typeOf() -> input.toLong() + typeOf() -> input.toFloat() + typeOf() -> { + if (input.trim().length == 1) { + input.trim().toCharArray()[0] + } else throw InvalidInputTypeException(typeOf().toString()) + } + + typeOf() -> input + else -> throw InvalidInputTypeException(typeOf().toString()) + } + + return if (availableInputs != null) { + if (inputT.toString() in availableInputs.map { it.toString() }) Pair(ContinueCommand, inputT) + else throw InvalidElemInInputException() + } else Pair(ContinueCommand, inputT) + + } catch (e: NumberFormatException) { + println(e.message) + println("") + continue@readingAndChangingTypeCycle + } catch (e: InvalidInputTypeException) { + println(e.message) + println("") + continue@readingAndChangingTypeCycle + } catch (e: InvalidElemInInputException) { + println("There isn't this elem in list of available inputs. Try to repeat or enter return to exit in main menu: ") + continue@readingAndChangingTypeCycle + } + } + } + +} + +fun main() { + Main.work() } \ No newline at end of file