mirror of
https://github.com/ZhigalskiiIvan/TextStatisticsProject.git
synced 2024-11-09 18:01:51 +03:00
Compare commits
2 Commits
a8b42a7d42
...
150a40980a
Author | SHA1 | Date | |
---|---|---|---|
150a40980a | |||
ea792a3d0d |
@ -12,6 +12,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-cli:0.3.5")
|
||||||
implementation("org.jetbrains.lets-plot:lets-plot-kotlin:4.0.0")
|
implementation("org.jetbrains.lets-plot:lets-plot-kotlin:4.0.0")
|
||||||
implementation("org.jetbrains.lets-plot:lets-plot-batik:3.1.0")
|
implementation("org.jetbrains.lets-plot:lets-plot-batik:3.1.0")
|
||||||
implementation("org.jetbrains.lets-plot:lets-plot-jfx:3.1.0")
|
implementation("org.jetbrains.lets-plot:lets-plot-jfx:3.1.0")
|
||||||
|
@ -3,92 +3,87 @@ import kotlin.system.exitProcess
|
|||||||
import org.jetbrains.letsPlot.*
|
import org.jetbrains.letsPlot.*
|
||||||
import org.jetbrains.letsPlot.export.ggsave
|
import org.jetbrains.letsPlot.export.ggsave
|
||||||
import org.jetbrains.letsPlot.geom.*
|
import org.jetbrains.letsPlot.geom.*
|
||||||
import kotlin.reflect.typeOf
|
import kotlinx.cli.*
|
||||||
|
|
||||||
|
/** Recognizes the name of the text, which
|
||||||
/** Gives statistics of saved texts.
|
* user want to see statistics about and type of output.
|
||||||
|
* It calls methods of graphic building or printing data in console,
|
||||||
|
* build required for it objects.
|
||||||
*/
|
*/
|
||||||
class StatisticBuilder {
|
fun getStatistics(textData: TextData) {
|
||||||
|
|
||||||
/** Recognizes the name of the text, which
|
|
||||||
* user want to see statistics about and type of output.
|
|
||||||
* It calls methods of graphic building or printing data in console,
|
|
||||||
* build required for it objects.
|
|
||||||
*/
|
|
||||||
fun getStatistics(textData: TextData) {
|
|
||||||
|
|
||||||
if (!textData.haveText()) {
|
|
||||||
println("No saved texts")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val text = textData.getTextData("Input name of a text which you want to see statistics about.")
|
|
||||||
|
|
||||||
var counter = 1
|
|
||||||
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:")
|
|
||||||
|
|
||||||
val request = requestInput(listOf("console", "graphic", "both"))
|
|
||||||
request.first.exe()
|
|
||||||
|
|
||||||
when (request.second) {
|
|
||||||
"console" -> printStatisticsInConsole(text.getName(), wordsCountsMap.toMap())
|
|
||||||
"graphic" -> buildGraphic(text.getName(), wordsCountsMap.toMap())
|
|
||||||
"both" -> {
|
|
||||||
printStatisticsInConsole(text.getName(), wordsCountsMap.toMap())
|
|
||||||
buildGraphic(text.getName(), wordsCountsMap.toMap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!textData.haveText()) {
|
||||||
|
println("No saved texts")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Builds bar chart with data of mapOfSentenceNumToItsSize and saves image in file.
|
val text = textData.getTextData("Input name of a text which you want to see statistics about.")
|
||||||
* @param textName name of texts, which user want to see statistics about.
|
|
||||||
* @param mapOfSentenceNumToItsSize map of pairs of sentence numbers and their words count.
|
|
||||||
*/
|
|
||||||
private fun buildGraphic(textName: String, mapOfSentenceNumToItsSize: Map<Int, Int>) {
|
|
||||||
|
|
||||||
val data = mapOf(
|
var counter = 1
|
||||||
"words count" to mapOfSentenceNumToItsSize.map { it.value.toFloat() / mapOfSentenceNumToItsSize.size },
|
val wordsCountsMap = text.getSentencesList().map { counter++ to it.getWordsCount() }
|
||||||
)
|
|
||||||
|
|
||||||
val fig = ggplot(data) +
|
println("Print \"console\" if you have see data in console, \"graphic\" if you have see histogram \n" +
|
||||||
geomBar(
|
"and \"both\" if you have see them together:")
|
||||||
color = "white",
|
|
||||||
fill = "red"
|
|
||||||
) { x = "words count" } +
|
|
||||||
geomArea(
|
|
||||||
stat = Stat.density(),
|
|
||||||
color = "white",
|
|
||||||
fill = "pink",
|
|
||||||
alpha = 0.4
|
|
||||||
) { x = "words count" } +
|
|
||||||
ggsize(1400, 800)
|
|
||||||
|
|
||||||
println("Graphic was save in ${ggsave(fig, "$textName.png")}")
|
val request = requestInput(listOf("console", "graphic", "both"))
|
||||||
fig.show()
|
request.first.exe()
|
||||||
|
|
||||||
}
|
when (request.second) {
|
||||||
|
"console" -> printStatisticsInConsole(text.getName(), wordsCountsMap.toMap())
|
||||||
/** Prints statistics according to data from mapOfSentenceNumToItsSize.
|
"graphic" -> buildGraphic(text.getName(), wordsCountsMap.toMap())
|
||||||
* @param textName name of texts, which user want to see statistics about.
|
"both" -> {
|
||||||
* @param mapOfSentenceNumToItsSize map of pairs of sentence numbers and their words count.
|
printStatisticsInConsole(text.getName(), wordsCountsMap.toMap())
|
||||||
*/
|
buildGraphic(text.getName(), wordsCountsMap.toMap())
|
||||||
private fun printStatisticsInConsole(textName: String, mapOfSentenceNumToItsSize: Map<Int, Int>) {
|
|
||||||
|
|
||||||
val sectionTitle = "Text name: $textName"
|
|
||||||
println("-".repeat(sectionTitle.length))
|
|
||||||
println(sectionTitle)
|
|
||||||
println("-".repeat(sectionTitle.length))
|
|
||||||
|
|
||||||
val totalSentencesCount = mapOfSentenceNumToItsSize.size
|
|
||||||
var totalWordsCount = 0
|
|
||||||
for (sentInfo in mapOfSentenceNumToItsSize) {
|
|
||||||
totalWordsCount += sentInfo.value
|
|
||||||
}
|
}
|
||||||
println(
|
}
|
||||||
"""
|
}
|
||||||
|
|
||||||
|
/** Builds bar chart with data of mapOfSentenceNumToItsSize and saves image in file.
|
||||||
|
* @param textName name of texts, which user want to see statistics about.
|
||||||
|
* @param mapOfSentenceNumToItsSize map of pairs of sentence numbers and their words count.
|
||||||
|
*/
|
||||||
|
private fun buildGraphic(textName: String, mapOfSentenceNumToItsSize: Map<Int, Int>) {
|
||||||
|
|
||||||
|
val data = mapOf(
|
||||||
|
"words count" to mapOfSentenceNumToItsSize.map { it.value.toFloat() / mapOfSentenceNumToItsSize.size },
|
||||||
|
)
|
||||||
|
|
||||||
|
val fig = ggplot(data) +
|
||||||
|
geomBar(
|
||||||
|
color = "white",
|
||||||
|
fill = "red"
|
||||||
|
) { x = "words count" } +
|
||||||
|
geomArea(
|
||||||
|
stat = Stat.density(),
|
||||||
|
color = "white",
|
||||||
|
fill = "pink",
|
||||||
|
alpha = 0.4
|
||||||
|
) { x = "words count" } +
|
||||||
|
ggsize(1400, 800)
|
||||||
|
|
||||||
|
println("Graphic was save in ${ggsave(fig, "$textName.png")}")
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Prints statistics according to data from mapOfSentenceNumToItsSize.
|
||||||
|
* @param textName name of texts, which user want to see statistics about.
|
||||||
|
* @param mapOfSentenceNumToItsSize map of pairs of sentence numbers and their words count.
|
||||||
|
*/
|
||||||
|
private fun printStatisticsInConsole(textName: String, mapOfSentenceNumToItsSize: Map<Int, Int>) {
|
||||||
|
|
||||||
|
val sectionTitle = "Text name: $textName"
|
||||||
|
println("-".repeat(sectionTitle.length))
|
||||||
|
println(sectionTitle)
|
||||||
|
println("-".repeat(sectionTitle.length))
|
||||||
|
|
||||||
|
val totalSentencesCount = mapOfSentenceNumToItsSize.size
|
||||||
|
var totalWordsCount = 0
|
||||||
|
for (sentInfo in mapOfSentenceNumToItsSize) {
|
||||||
|
totalWordsCount += sentInfo.value
|
||||||
|
}
|
||||||
|
println(
|
||||||
|
"""
|
||||||
|Statistics:
|
|Statistics:
|
||||||
|[count of sentences]:
|
|[count of sentences]:
|
||||||
|--- $totalSentencesCount
|
|--- $totalSentencesCount
|
||||||
@ -99,125 +94,119 @@ class StatisticBuilder {
|
|||||||
|[num of sentence: count of words in it]:
|
|[num of sentence: count of words in it]:
|
||||||
|--- ${mapOfSentenceNumToItsSize.toList().joinToString("; ") { "${it.first} contains ${it.second}" }}.
|
|--- ${mapOfSentenceNumToItsSize.toList().joinToString("; ") { "${it.first} contains ${it.second}" }}.
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
)
|
)
|
||||||
println("-".repeat(sectionTitle.length))
|
println("-".repeat(sectionTitle.length))
|
||||||
println("Done!\n")
|
println("Done!\n")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Used for reading text from a file or console. */
|
/** Asks the user which where they want to read the text from and
|
||||||
class TextReader {
|
* calls special for file- and console- reading methods according the answer.
|
||||||
|
*/
|
||||||
|
fun readNewText(textData: TextData) {
|
||||||
|
|
||||||
/** Asks the user which where they want to read the text from and
|
println("Where do you want to add the text: from the console or a file?")
|
||||||
* calls special for file- and console- reading methods according the answer.
|
|
||||||
*/
|
|
||||||
fun readNewText(textData: TextData) {
|
|
||||||
|
|
||||||
println("Where do you want to add the text: from the console or a file?")
|
val kindOfSource = requestInput(listOf("console", "file"))
|
||||||
|
kindOfSource.first.exe()
|
||||||
|
|
||||||
val kindOfSource = requestInput(listOf("console", "file"))
|
when (kindOfSource.second) {
|
||||||
kindOfSource.first.exe()
|
"console" -> readFromConsole(textData)
|
||||||
|
"file" -> readFromFile(textData)
|
||||||
when (kindOfSource.second) {
|
|
||||||
"console" -> readFromConsole(textData)
|
|
||||||
"file" -> readFromFile(textData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Read from console the name of text, checks that it hasn't saved yet and its contents,
|
|
||||||
* asks if entered text is not correct and re-calls itself or
|
|
||||||
* calls method of adding received text to data.
|
|
||||||
*/
|
|
||||||
private fun readFromConsole(textData: TextData) {
|
|
||||||
|
|
||||||
println("Input name of a text:")
|
|
||||||
if (textData.haveText()) println("Unavailable(existing) names: ${textData.getTextNamesInString()}.")
|
|
||||||
val nameRequest = requestInput(unavailableInputs = textData.getTextNamesList())
|
|
||||||
nameRequest.first.exe()
|
|
||||||
|
|
||||||
val name = nameRequest.second.toString()
|
|
||||||
|
|
||||||
println("Input a text content(after input text press enter twice):")
|
|
||||||
var content = ""
|
|
||||||
|
|
||||||
var itWasNewParYet = false
|
|
||||||
readCycle@ while (true) {
|
|
||||||
val nextPart = readln()
|
|
||||||
if (nextPart.isEmpty()) {
|
|
||||||
if (itWasNewParYet) break@readCycle
|
|
||||||
else {
|
|
||||||
content += "\n"
|
|
||||||
itWasNewParYet = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
itWasNewParYet = false
|
|
||||||
content += "$nextPart\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("Was input data right?[yes, no]:")
|
|
||||||
|
|
||||||
val correctInputRequest = requestInput(listOf("yes", "no"))
|
|
||||||
correctInputRequest.first.exe()
|
|
||||||
|
|
||||||
if (correctInputRequest.second == "yes") addTextToData(textData, name, content)
|
|
||||||
else readFromConsole(textData)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Asks for the name of text, path to file to read text from,
|
|
||||||
* checks for its existing, reads contents and,
|
|
||||||
* asks if entered names is not correct and re-calls itself or
|
|
||||||
* calls method of adding received text to data.
|
|
||||||
*/
|
|
||||||
private fun readFromFile(textData: TextData) {
|
|
||||||
|
|
||||||
println("Input a name of a text:")
|
|
||||||
val name = readln()
|
|
||||||
|
|
||||||
println("Input path to file:")
|
|
||||||
val contentsFile: File
|
|
||||||
|
|
||||||
pathReadCycle@ while (true) {
|
|
||||||
val pathRequest = requestInput<String>()
|
|
||||||
pathRequest.first.exe()
|
|
||||||
val filePath = pathRequest.second.toString()
|
|
||||||
|
|
||||||
val testFile = File(filePath)
|
|
||||||
|
|
||||||
if (!testFile.exists()) {
|
|
||||||
println("Incorrect path. Repeat the input:")
|
|
||||||
continue@pathReadCycle
|
|
||||||
} else {
|
|
||||||
contentsFile = testFile
|
|
||||||
break@pathReadCycle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val content = contentsFile.readText()
|
|
||||||
|
|
||||||
print("Input was correct?[yes, no]: ")
|
|
||||||
val correctInputRequest = requestInput(listOf("yes", "no"))
|
|
||||||
correctInputRequest.first.exe()
|
|
||||||
|
|
||||||
when (correctInputRequest.second) {
|
|
||||||
"yes" -> addTextToData(textData, name, content)
|
|
||||||
"no" -> readFromFile(textData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls method of TextData class to add new text in set
|
|
||||||
* of tracked texts.
|
|
||||||
* @param textName name of new text.
|
|
||||||
* @param content content of new text.
|
|
||||||
*/
|
|
||||||
private fun addTextToData(textData: TextData, textName: String, content: String) =
|
|
||||||
textData.addNewText(textName, content)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Read from console the name of text, checks that it hasn't saved yet and its contents,
|
||||||
|
* asks if entered text is not correct and re-calls itself or
|
||||||
|
* calls method of adding received text to data.
|
||||||
|
*/
|
||||||
|
private fun readFromConsole(textData: TextData) {
|
||||||
|
|
||||||
|
println("Input name of a text:")
|
||||||
|
if (textData.haveText()) println("Unavailable(existing) names: ${textData.getTextNamesInString()}.")
|
||||||
|
val nameRequest = requestInput(unavailableInputs = textData.getTextNamesList())
|
||||||
|
nameRequest.first.exe()
|
||||||
|
|
||||||
|
val name = nameRequest.second!!
|
||||||
|
|
||||||
|
println("Input a text content(after input text press enter twice):")
|
||||||
|
var content = ""
|
||||||
|
|
||||||
|
var itWasNewParYet = false
|
||||||
|
while (true) {
|
||||||
|
val nextPart = readln()
|
||||||
|
if (nextPart.isEmpty()) {
|
||||||
|
if (itWasNewParYet) break
|
||||||
|
else {
|
||||||
|
content += "\n"
|
||||||
|
itWasNewParYet = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
itWasNewParYet = false
|
||||||
|
content += "$nextPart\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Was input data right?[yes, no]:")
|
||||||
|
|
||||||
|
val correctInputRequest = requestInput(listOf("yes", "no"))
|
||||||
|
correctInputRequest.first.exe()
|
||||||
|
|
||||||
|
if (correctInputRequest.second == "yes") addTextToData(textData, name, content)
|
||||||
|
else readFromConsole(textData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Asks for the name of text, path to file to read text from,
|
||||||
|
* checks for its existing, reads contents and,
|
||||||
|
* asks if entered names is not correct and re-calls itself or
|
||||||
|
* calls method of adding received text to data.
|
||||||
|
*/
|
||||||
|
private fun readFromFile(textData: TextData) {
|
||||||
|
|
||||||
|
println("Input a name of a text:")
|
||||||
|
val name = readln()
|
||||||
|
|
||||||
|
println("Input path to file:")
|
||||||
|
val contentsFile: File
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val pathRequest = requestInput()
|
||||||
|
pathRequest.first.exe()
|
||||||
|
val filePath = pathRequest.second!!
|
||||||
|
|
||||||
|
val testFile = File(filePath)
|
||||||
|
|
||||||
|
if (!testFile.exists()) {
|
||||||
|
println("Incorrect path. Repeat the input:")
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
contentsFile = testFile
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val content = contentsFile.readText()
|
||||||
|
|
||||||
|
print("Input was correct?[yes, no]: ")
|
||||||
|
val correctInputRequest = requestInput(listOf("yes", "no"))
|
||||||
|
correctInputRequest.first.exe()
|
||||||
|
|
||||||
|
when (correctInputRequest.second) {
|
||||||
|
"yes" -> addTextToData(textData, name, content)
|
||||||
|
"no" -> readFromFile(textData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls method of TextData class to add new text in set
|
||||||
|
* of tracked texts.
|
||||||
|
* @param textName name of new text.
|
||||||
|
* @param content content of new text.
|
||||||
|
*/
|
||||||
|
private fun addTextToData(textData: TextData, textName: String, content: String) =
|
||||||
|
textData.addNewText(textName, content)
|
||||||
|
|
||||||
|
|
||||||
/** Stores data about tracking texts,
|
/** Stores data about tracking texts,
|
||||||
* includes methods for work with them due the adding.
|
* includes methods for work with them due the adding.
|
||||||
*/
|
*/
|
||||||
@ -226,7 +215,6 @@ class TextData {
|
|||||||
/** list of monitored texts. */
|
/** list of monitored texts. */
|
||||||
private val textsList = mutableListOf<Text>()
|
private val textsList = mutableListOf<Text>()
|
||||||
|
|
||||||
|
|
||||||
fun haveText(): Boolean = textsList.isNotEmpty()
|
fun haveText(): Boolean = textsList.isNotEmpty()
|
||||||
|
|
||||||
/** Method for removing text from watch list. Asks for a name of a text
|
/** Method for removing text from watch list. Asks for a name of a text
|
||||||
@ -234,7 +222,6 @@ class TextData {
|
|||||||
*/
|
*/
|
||||||
fun removeText() {
|
fun removeText() {
|
||||||
|
|
||||||
|
|
||||||
if (!haveText()) {
|
if (!haveText()) {
|
||||||
println("No saved texts")
|
println("No saved texts")
|
||||||
return
|
return
|
||||||
@ -284,20 +271,18 @@ class TextData {
|
|||||||
* @return Text type object
|
* @return Text type object
|
||||||
*/
|
*/
|
||||||
fun getTextData(message: String = "Input name of a text"): Text {
|
fun getTextData(message: String = "Input name of a text"): Text {
|
||||||
|
|
||||||
|
|
||||||
println(message)
|
println(message)
|
||||||
println("Saved texts: ${getTextNamesInString()}.")
|
println("Saved texts: ${getTextNamesInString()}.")
|
||||||
|
|
||||||
val nameRequest = requestInput(getTextNamesList())
|
val nameRequest = requestInput(getTextNamesList())
|
||||||
nameRequest.first.exe()
|
nameRequest.first.exe()
|
||||||
|
|
||||||
return getTextByName(nameRequest.second.toString())!!
|
return getTextByName(nameRequest.second!!)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Object used for getting text from the string information. */
|
/** Object used for getting text from the string information. */
|
||||||
object TextAnalyzer {
|
private object TextAnalyzer {
|
||||||
|
|
||||||
private val DELIMITERS = Regex("[!?.]+\\s+")
|
private val DELIMITERS = Regex("[!?.]+\\s+")
|
||||||
private val WHITESPACES = Regex("\\s+")
|
private val WHITESPACES = Regex("\\s+")
|
||||||
@ -310,7 +295,6 @@ class TextData {
|
|||||||
*/
|
*/
|
||||||
fun getTextObjFromContents(name: String, content: String): Text {
|
fun getTextObjFromContents(name: String, content: String): Text {
|
||||||
|
|
||||||
|
|
||||||
var sentencesCount = 1
|
var sentencesCount = 1
|
||||||
val listOfSentences = mutableListOf<Text.Sentence>()
|
val listOfSentences = mutableListOf<Text.Sentence>()
|
||||||
|
|
||||||
@ -363,22 +347,18 @@ fun exit(): Nothing {
|
|||||||
/** Reads commands from the console and storing data about
|
/** Reads commands from the console and storing data about
|
||||||
* the functions they should execute.
|
* the functions they should execute.
|
||||||
*/
|
*/
|
||||||
class CommandCenter(
|
class CommandCenter(private val textData: TextData) {
|
||||||
private val textData: TextData,
|
|
||||||
private val textReader: TextReader,
|
|
||||||
private val statisticBuilder: StatisticBuilder
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val exitCommand = Command("exit", ::exit)
|
private val exitCommand = Command("exit", ::exit)
|
||||||
private val addCommand = Command("add text") { textReader.readNewText(textData) }
|
private val addCommand = Command("add text") { readNewText(textData) }
|
||||||
private val showStatisticsCommand = Command("show statistics") { statisticBuilder.getStatistics(textData) }
|
private val showStatisticsCommand = Command("show statistics") { getStatistics(textData) }
|
||||||
private val removeTextCommand = Command("remove text") { textData.removeText() }
|
private val removeTextCommand = Command("remove text") { textData.removeText() }
|
||||||
|
|
||||||
private val commandsList = listOf(exitCommand, addCommand, showStatisticsCommand, removeTextCommand)
|
private val commandsList = listOf(exitCommand, addCommand, showStatisticsCommand, removeTextCommand)
|
||||||
private val commandsNames = commandsList.map { it.name }
|
private val commandsNames = commandsList.map { it.name }
|
||||||
|
|
||||||
/** Stores command and its name */
|
/** Stores command and its name */
|
||||||
class Command(val name: String, val executingFun: () -> Unit)
|
private class Command(val name: String, val executingFun: () -> Unit)
|
||||||
|
|
||||||
/** Prints list of names of available commands, requests the name and
|
/** Prints list of names of available commands, requests the name and
|
||||||
* returns corresponding to entered name function.
|
* returns corresponding to entered name function.
|
||||||
@ -390,39 +370,24 @@ class CommandCenter(
|
|||||||
val commandNameRequest = requestInput(commandsNames)
|
val commandNameRequest = requestInput(commandsNames)
|
||||||
commandNameRequest.first.exe()
|
commandNameRequest.first.exe()
|
||||||
|
|
||||||
val funName = commandNameRequest.second.toString()
|
val funName = commandNameRequest.second
|
||||||
|
|
||||||
return commandsList.find { it.name == funName }!!.executingFun
|
return commandsList.find { it.name == funName }!!.executingFun
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Custom exception being thrown if user want to return to the menu. */
|
|
||||||
class ReturnException : Exception()
|
|
||||||
|
|
||||||
/** Custom exception being thrown if input can't be converted
|
|
||||||
* to the requested type.
|
|
||||||
*/
|
|
||||||
class InvalidInputTypeException : Exception()
|
|
||||||
|
|
||||||
/** Custom exception being thrown if input doesn't match the list
|
|
||||||
* of possible values.
|
|
||||||
*/
|
|
||||||
class InvalidElemInInputException : Exception()
|
|
||||||
|
|
||||||
|
|
||||||
/** Function repeating the process of calling functions returned by
|
/** Function repeating the process of calling functions returned by
|
||||||
* CommandCenter. If ReturnException was thrown, it is caught here,
|
* CommandCenter. If ReturnException was thrown, it is caught here,
|
||||||
* last iteration breaks and new one is called.
|
* last iteration breaks and new one is called.
|
||||||
*/
|
*/
|
||||||
fun workCycle(commandCenter: CommandCenter) {
|
fun workCycle(commandCenter: CommandCenter) {
|
||||||
mainCycle@ while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
(commandCenter.readCommandFromConsole())()
|
(commandCenter.readCommandFromConsole())()
|
||||||
} catch (e: ReturnException) {
|
} catch (e: ReturnException) {
|
||||||
println("You have been returned in main menu.")
|
println("You have been returned in main menu.")
|
||||||
continue@mainCycle
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,73 +403,31 @@ fun workCycle(commandCenter: CommandCenter) {
|
|||||||
* @return a pair of function, which could be called after the request from this function to return
|
* @return a pair of function, which could be called after the request from this function to return
|
||||||
* if user want it or continue and value that the user has selected from the list of available.
|
* if user want it or continue and value that the user has selected from the list of available.
|
||||||
*/
|
*/
|
||||||
inline fun <reified T> requestInput(
|
fun requestInput(
|
||||||
availableInputs: List<T>? = null,
|
availableInputs: List<Any>? = null,
|
||||||
unavailableInputs: List<T>? = null
|
unavailableInputs: List<Any>? = null
|
||||||
): Pair<InputOutcomeCommand, Any> {
|
): Pair<InputOutcomeCommand, String?> {
|
||||||
|
|
||||||
var inputT: Any
|
val regexAvailableInputs = availableInputs?.joinToString("|")?.toRegex() ?: Regex(".*")
|
||||||
|
val regexUnavailableInputs = unavailableInputs?.joinToString("|")?.toRegex() ?: Regex("")
|
||||||
readingAndChangingTypeCycle@ while (true) {
|
val returnRegex = Regex("return")
|
||||||
|
|
||||||
|
while (true) {
|
||||||
val input = readln().trim()
|
val input = readln().trim()
|
||||||
if (input == "return") return Pair(ReturnCommand(), "")
|
|
||||||
|
|
||||||
try {
|
return when {
|
||||||
inputT = when (typeOf<T>()) {
|
input.matches(regexAvailableInputs) && !input.matches(regexUnavailableInputs) ->
|
||||||
typeOf<Int>() -> input.toInt()
|
ContinueCommand() to input
|
||||||
typeOf<Double>() -> input.toDouble()
|
|
||||||
typeOf<Boolean>() -> input.toBoolean()
|
|
||||||
typeOf<Byte>() -> input.toByte()
|
|
||||||
typeOf<Long>() -> input.toLong()
|
|
||||||
typeOf<Float>() -> input.toFloat()
|
|
||||||
typeOf<Char>() -> {
|
|
||||||
if (input.trim().length == 1) {
|
|
||||||
input.trim().toCharArray()[0]
|
|
||||||
} else throw InvalidInputTypeException()
|
|
||||||
}
|
|
||||||
|
|
||||||
typeOf<String>() -> input
|
input.matches(returnRegex) -> ReturnCommand() to null
|
||||||
else -> throw InvalidInputTypeException()
|
else -> {
|
||||||
|
println("There isn't this elem in list of available inputs. Try to repeat or enter return to exit in main menu: ")
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
|
||||||
availableInputs != null && unavailableInputs != null -> {
|
|
||||||
if (inputT.toString() in availableInputs.map { it.toString() } &&
|
|
||||||
inputT.toString() !in unavailableInputs.map { it.toString() }) Pair(ContinueCommand(), inputT)
|
|
||||||
else throw InvalidElemInInputException()
|
|
||||||
}
|
|
||||||
|
|
||||||
availableInputs != null -> {
|
|
||||||
if (inputT.toString() in availableInputs.map { it.toString() }) Pair(ContinueCommand(), inputT)
|
|
||||||
else throw InvalidElemInInputException()
|
|
||||||
}
|
|
||||||
|
|
||||||
unavailableInputs != null -> {
|
|
||||||
if (inputT.toString() !in unavailableInputs.map { it.toString() }) Pair(ContinueCommand(), inputT)
|
|
||||||
else throw InvalidElemInInputException()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> Pair(ContinueCommand(), inputT)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (e: NumberFormatException) {
|
|
||||||
continue@readingAndChangingTypeCycle
|
|
||||||
} catch (e: InvalidInputTypeException) {
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Interface used to existing commands objects, whose exe value
|
/** Interface used to existing commands objects, whose exe value
|
||||||
* stores function which calls after requesting from console in
|
* stores function which calls after requesting from console in
|
||||||
* requestInput function.
|
* requestInput function.
|
||||||
@ -531,13 +454,14 @@ class ReturnCommand : InputOutcomeCommand {
|
|||||||
override val exe: () -> Unit = throw ReturnException()
|
override val exe: () -> Unit = throw ReturnException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Custom exception being thrown if user want to return to the menu. */
|
||||||
|
class ReturnException : Exception()
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|
||||||
val textData = TextData()
|
val textData = TextData()
|
||||||
val statisticBuilder = StatisticBuilder()
|
val commandCenter = CommandCenter(textData)
|
||||||
val textReader = TextReader()
|
|
||||||
|
|
||||||
val commandCenter = CommandCenter(textData, textReader, statisticBuilder)
|
|
||||||
|
|
||||||
workCycle(commandCenter)
|
workCycle(commandCenter)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user