fuck me
This commit is contained in:
+25
-23
@@ -1,7 +1,7 @@
|
||||
import collection.CollectionManager
|
||||
import commands.*
|
||||
import file.FileManager
|
||||
import input.ConsoleInputManager
|
||||
import input.IOManager
|
||||
import input.InputManager
|
||||
import runner.CommandInvoker
|
||||
|
||||
@@ -24,7 +24,7 @@ fun main(args: Array<String>) {
|
||||
val fileManager = FileManager(filePath)
|
||||
val manager = CollectionManager()
|
||||
val invoker = CommandInvoker()
|
||||
val inputManager = ConsoleInputManager()
|
||||
val inputManager = IOManager()
|
||||
|
||||
// Загружаем данные из файла
|
||||
val loaded = fileManager.read()
|
||||
@@ -34,7 +34,7 @@ fun main(args: Array<String>) {
|
||||
registerCommands(invoker, manager, fileManager, inputManager)
|
||||
|
||||
// Водила, стартуем. Я сказала стартуем!
|
||||
println("Коллекция загружена. Введите 'help' для справки.")
|
||||
inputManager.print("Коллекция загружена. Введите 'help' для справки.")
|
||||
runRepl(inputManager, invoker)
|
||||
}
|
||||
|
||||
@@ -47,19 +47,19 @@ fun main(args: Array<String>) {
|
||||
* @param inputManager источник ввода
|
||||
* @param invoker инвокер команд
|
||||
*/
|
||||
fun runRepl(inputManager: InputManager, invoker: CommandInvoker) {
|
||||
var isRunning = true
|
||||
fun runRepl(
|
||||
inputManager: InputManager,
|
||||
invoker: CommandInvoker
|
||||
) {
|
||||
|
||||
// exitProcess мне нравился больше
|
||||
invoker.register(ExitCommand { isRunning = false })
|
||||
|
||||
while (isRunning) {
|
||||
while (true) {
|
||||
val line = inputManager.readLine() ?: break
|
||||
if (line.isBlank()) continue
|
||||
if (line == "exit") break
|
||||
|
||||
// if command.isTerminating -> break
|
||||
invoker.execute(line)
|
||||
}
|
||||
|
||||
println("\nНу ладно.")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,25 +74,27 @@ fun registerCommands(
|
||||
invoker: CommandInvoker,
|
||||
manager: CollectionManager,
|
||||
fileManager: FileManager,
|
||||
inputManager: InputManager
|
||||
) {
|
||||
inputManager: IOManager,
|
||||
|
||||
) {
|
||||
val activeScripts = mutableSetOf<String>()
|
||||
|
||||
listOf(
|
||||
HelpCommand(invoker),
|
||||
InfoCommand(manager),
|
||||
ShowCommand(manager),
|
||||
HelpCommand(invoker, inputManager),
|
||||
InfoCommand(manager, inputManager),
|
||||
ShowCommand(manager, inputManager),
|
||||
AddCommand(manager, inputManager),
|
||||
UpdateCommand(manager, inputManager),
|
||||
RemoveByIdCommand(manager),
|
||||
ClearCommand(manager),
|
||||
RemoveByIdCommand(manager, inputManager),
|
||||
ClearCommand(manager, inputManager),
|
||||
SaveCommand(manager, fileManager),
|
||||
ExecuteScriptCommand(invoker),
|
||||
ExecuteScriptCommand(invoker, inputManager),
|
||||
AddIfMaxCommand(manager, inputManager),
|
||||
AddIfMinCommand(manager, inputManager),
|
||||
HistoryCommand(invoker),
|
||||
SumOfMinutesCommand(manager),
|
||||
MinByNameCommand(manager),
|
||||
PrintDescendingMinutesCommand(manager)
|
||||
HistoryCommand(invoker, inputManager),
|
||||
SumOfMinutesCommand(manager, inputManager),
|
||||
MinByNameCommand(manager, inputManager),
|
||||
PrintDescendingMinutesCommand(manager,inputManager),
|
||||
ExitCommand(inputManager)
|
||||
).forEach { invoker.register(it) }
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@ import input.InputManager
|
||||
*/
|
||||
class AddCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val inputManager: InputManager
|
||||
private val inputManager: InputManager,
|
||||
) : Command {
|
||||
override val name = "add"
|
||||
override val description = "добавить новый элемент в коллекцию"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
val human = HumanBeingBuilder(inputManager).build()
|
||||
if (manager.add(human)) println("Элемент добавлен: ${human.name} [${human.id}]")
|
||||
else println("Элемент уже существует в коллекции.")
|
||||
if (manager.add(human)) inputManager.print("Элемент добавлен: ${human.name} [${human.id}]")
|
||||
else inputManager.print("Элемент уже существует в коллекции.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import input.InputManager
|
||||
*/
|
||||
class AddIfMaxCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val inputManager: InputManager
|
||||
private val inputManager: InputManager,
|
||||
) : Command {
|
||||
override val name = "add_if_max"
|
||||
override val description = "добавить элемент, если он больше максимального"
|
||||
@@ -20,9 +20,9 @@ class AddIfMaxCommand(
|
||||
val max = manager.getMax()
|
||||
if (max == null || human > max) {
|
||||
manager.add(human)
|
||||
println("Элемент добавлен (превышает максимум).")
|
||||
inputManager.print("Элемент добавлен (превышает максимум).")
|
||||
} else {
|
||||
println("Элемент не добавлен: не превышает текущий максимум (${max.name}).")
|
||||
inputManager.print("Элемент не добавлен: не превышает текущий максимум (${max.name}).")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ class AddIfMinCommand(
|
||||
val min = manager.getMin()
|
||||
if (min == null || human < min) {
|
||||
manager.add(human)
|
||||
println("Элемент добавлен (меньше минимума).")
|
||||
inputManager.print("Элемент добавлен (меньше минимума).")
|
||||
} else {
|
||||
println("Элемент не добавлен: не меньше текущего минимума (${min.name}).")
|
||||
inputManager.print("Элемент не добавлен: не меньше текущего минимума (${min.name}).")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.InputManager
|
||||
|
||||
/**
|
||||
* Очищает коллекцию.
|
||||
* @property manager менеджер коллекции
|
||||
*/
|
||||
class ClearCommand(private val manager: CollectionManager) : Command {
|
||||
class ClearCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "clear"
|
||||
override val description = "очистить коллекцию"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
manager.clear()
|
||||
println("Коллекция очищена.")
|
||||
console.print("Коллекция очищена.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ package commands
|
||||
* Базовый интерфейс для всех команд приложения.
|
||||
*/
|
||||
interface Command {
|
||||
|
||||
// добавить перменную для
|
||||
|
||||
|
||||
/** Имя команды. */
|
||||
val name: String
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package commands
|
||||
|
||||
import input.InputManager
|
||||
import runner.CommandInvoker
|
||||
import runner.CommandQueue
|
||||
|
||||
@@ -12,36 +13,42 @@ import runner.CommandQueue
|
||||
*
|
||||
* Такой подход гарантирует, что все файлы прочитаны до начала выполнения.
|
||||
*/
|
||||
class ExecuteScriptCommand(private val invoker: CommandInvoker) : Command {
|
||||
class ExecuteScriptCommand(
|
||||
private val invoker: CommandInvoker,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "execute_script"
|
||||
override val description = "выполнить скрипт из файла: execute_script <file>"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
if (args.isEmpty()) {
|
||||
println("[Ошибка] Укажите путь к файлу. Пример: execute_script script.txt")
|
||||
console.print("[Ошибка] Укажите путь к файлу. Пример: execute_script script.txt")
|
||||
return
|
||||
}
|
||||
|
||||
val filePath = args[0]
|
||||
|
||||
// я манал это всё
|
||||
println("Чтение скрипта '$filePath'...")
|
||||
console.print("Чтение скрипта '$filePath'...")
|
||||
|
||||
// inputmanager добавить источник, Scanner file
|
||||
val queue = CommandQueue()
|
||||
queue.loadFromScript(filePath)
|
||||
|
||||
if (queue.isEmpty()) {
|
||||
println("Текст Скриптонита пустой или не найден.")
|
||||
console.print("Текст Скриптонита пустой или не найден.")
|
||||
return
|
||||
}
|
||||
|
||||
println("Прочитано команд: ${queue.size()}. Начинаем выполнение...")
|
||||
console.print("Прочитано команд: ${queue.size()}. Начинаем выполнение...")
|
||||
|
||||
// это уже есть
|
||||
while (!queue.isEmpty()) {
|
||||
val line = queue.dequeue() ?: break
|
||||
println(" [скриптонит] > $line")
|
||||
console.print(" [скриптонит] > $line")
|
||||
invoker.execute(line)
|
||||
}
|
||||
|
||||
println("Скриптонит зачитал '$filePath'.")
|
||||
console.print("Скриптонит зачитал '$filePath'.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package commands
|
||||
|
||||
import input.InputManager
|
||||
|
||||
/**
|
||||
* Завершает программу без сохранения. Теперь это Callback
|
||||
*/
|
||||
class ExitCommand(private val onExit: () -> Unit) : Command {
|
||||
class ExitCommand(
|
||||
private val console: InputManager,
|
||||
) : Command {
|
||||
override val name = "exit"
|
||||
override val description = "завершить программу"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
println("До свидания!")
|
||||
onExit()
|
||||
console.print("До свидания!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
package commands
|
||||
|
||||
import input.InputManager
|
||||
import runner.CommandInvoker
|
||||
|
||||
/**
|
||||
* Выводит справку по всем доступным командам.
|
||||
* @property invoker инвокер, из которого берётся реестр команд
|
||||
*/
|
||||
class HelpCommand(private val invoker: CommandInvoker) : Command {
|
||||
class HelpCommand(
|
||||
private val invoker: CommandInvoker,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "help"
|
||||
override val description = "вывести справку по доступным командам"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
invoker.getCommands().values
|
||||
.sortedBy { it.name }
|
||||
.forEach { println(" ${it.name.padEnd(40)} — ${it.description}") }
|
||||
.forEach { console.print(" ${it.name.padEnd(40)} — ${it.description}") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
package commands
|
||||
|
||||
import input.InputManager
|
||||
import runner.CommandInvoker
|
||||
|
||||
/**
|
||||
* Выводит последние 12 команд без аргументов.
|
||||
* @property invoker инвокер с историей
|
||||
*/
|
||||
class HistoryCommand(private val invoker: CommandInvoker) : Command {
|
||||
class HistoryCommand(
|
||||
private val invoker: CommandInvoker,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "history"
|
||||
override val description = "вывести последние 12 команд"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
val history = invoker.getHistory()
|
||||
if (history.isEmpty()) {
|
||||
println("История пуста.")
|
||||
console.print("История пуста.")
|
||||
return
|
||||
}
|
||||
history.forEachIndexed { i, cmd -> println(" ${i + 1}. $cmd") }
|
||||
history.forEachIndexed { i, cmd -> console.print(" ${i + 1}. $cmd") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.InputManager
|
||||
|
||||
/**
|
||||
* Выводит информацию о коллекции (тип, дата инициализации, размер).
|
||||
* @property manager менеджер коллекции
|
||||
*/
|
||||
class InfoCommand(private val manager: CollectionManager) : Command {
|
||||
class InfoCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "info"
|
||||
override val description = "вывести информацию о коллекции"
|
||||
|
||||
override fun execute(args: List<String>) = println(manager.getInfo())
|
||||
override fun execute(args: List<String>) = console.print(manager.getInfo())
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.IOManager
|
||||
|
||||
/**
|
||||
* Выводит любой элемент с минимальным значением поля [models.HumanBeing.name].
|
||||
*/
|
||||
class MinByNameCommand(private val manager: CollectionManager) : Command {
|
||||
class MinByNameCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: IOManager
|
||||
) : Command {
|
||||
override val name = "min_by_name"
|
||||
override val description = "вывести элемент с минимальным именем"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
val min = manager.minByName()
|
||||
if (min == null) println("Коллекция пуста.")
|
||||
else println(min)
|
||||
if (min == null) console.print("Коллекция пуста.")
|
||||
else console.print(min.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.IOManager
|
||||
|
||||
/**
|
||||
* Выводит значения поля [models.HumanBeing.minutesOfWaiting] в порядке убывания.
|
||||
*/
|
||||
class PrintDescendingMinutesCommand(private val manager: CollectionManager) : Command {
|
||||
class PrintDescendingMinutesCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: IOManager
|
||||
) : Command {
|
||||
override val name = "print_field_descending_minutes_of_waiting"
|
||||
override val description = "вывести minutesOfWaiting в порядке убывания"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
val values = manager.getMinutesOfWaitingDescending()
|
||||
if (values.isEmpty()) println("Коллекция пуста.")
|
||||
else values.forEach { println(it) }
|
||||
if (values.isEmpty()) console.print("Коллекция пуста.")
|
||||
else values.forEach { console.print(it.toString()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.IOManager
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Удаляет элемент из коллекции по его id.
|
||||
* Синтаксис: remove_by_id <uuid>
|
||||
*/
|
||||
class RemoveByIdCommand(private val manager: CollectionManager) : Command {
|
||||
class RemoveByIdCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: IOManager
|
||||
) : Command {
|
||||
override val name = "remove_by_id"
|
||||
override val description = "удалить элемент по id: remove_by_id <uuid>"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
if (args.isEmpty()) {
|
||||
println("[Ошибка] Укажите id. Пример: remove_by_id <uuid>")
|
||||
console.print("[Ошибка] Укажите id. Пример: remove_by_id <uuid>")
|
||||
return
|
||||
}
|
||||
val id = try {
|
||||
UUID.fromString(args[0])
|
||||
} catch (e: IllegalArgumentException) {
|
||||
println("[Ошибка] Некорректный UUID: '${args[0]}'")
|
||||
console.print("[Ошибка] Некорректный UUID: '${args[0]}'")
|
||||
return
|
||||
}
|
||||
if (manager.removeById(id)) println("Элемент удалён.")
|
||||
else println("[Ошибка] Элемент с id '$id' не найден.")
|
||||
if (manager.removeById(id)) console.print("Элемент удалён.")
|
||||
else console.print("[Ошибка] Элемент с id '$id' не найден.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import file.FileManager
|
||||
*/
|
||||
class SaveCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val fileManager: FileManager
|
||||
private val fileManager: FileManager,
|
||||
) : Command {
|
||||
override val name = "save"
|
||||
override val description = "сохранить коллекцию в файл"
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.InputManager
|
||||
|
||||
/**
|
||||
* Выводит все элементы коллекции в строковом представлении.
|
||||
* @property manager менеджер коллекции
|
||||
*/
|
||||
class ShowCommand(private val manager: CollectionManager) : Command {
|
||||
class ShowCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "show"
|
||||
override val description = "вывести все элементы коллекции"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
if (manager.isEmpty()) {
|
||||
println("Коллекция пуста.")
|
||||
console.print("Коллекция пуста.")
|
||||
return
|
||||
}
|
||||
manager.getAll().forEach { println(it) }
|
||||
manager.getAll().forEach { console.print(it.toString()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package commands
|
||||
|
||||
import collection.CollectionManager
|
||||
import input.InputManager
|
||||
|
||||
/**
|
||||
* Выводит сумму значений поля [models.HumanBeing.minutesOfWaiting].
|
||||
*/
|
||||
class SumOfMinutesCommand(private val manager: CollectionManager) : Command {
|
||||
class SumOfMinutesCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val console: InputManager
|
||||
) : Command {
|
||||
override val name = "sum_of_minutes_of_waiting"
|
||||
override val description = "вывести сумму minutesOfWaiting всех элементов"
|
||||
|
||||
override fun execute(args: List<String>) =
|
||||
println("Сумма minutesOfWaiting: ${manager.sumOfMinutesOfWaiting()}")
|
||||
console.print("Сумма minutesOfWaiting: ${manager.sumOfMinutesOfWaiting()}")
|
||||
}
|
||||
|
||||
@@ -12,28 +12,28 @@ import java.util.UUID
|
||||
*/
|
||||
class UpdateCommand(
|
||||
private val manager: CollectionManager,
|
||||
private val inputManager: InputManager
|
||||
private val inputManager: InputManager,
|
||||
) : Command {
|
||||
override val name = "update"
|
||||
override val description = "обновить элемент по id: update <uuid>"
|
||||
|
||||
override fun execute(args: List<String>) {
|
||||
if (args.isEmpty()) {
|
||||
println("[Ошибка] Укажите id элемента. Пример: update <uuid>")
|
||||
inputManager.print("[Ошибка] Укажите id элемента. Пример: update <uuid>")
|
||||
return
|
||||
}
|
||||
val id = try {
|
||||
UUID.fromString(args[0])
|
||||
} catch (e: IllegalArgumentException) {
|
||||
println("[Ошибка] Некорректный UUID: '${args[0]}'")
|
||||
inputManager.print("[Ошибка] Некорректный UUID: '${args[0]}'")
|
||||
return
|
||||
}
|
||||
if (manager.getById(id) == null) {
|
||||
println("[Ошибка] Элемент с id '$id' не найден.")
|
||||
inputManager.print("[Ошибка] Элемент с id '$id' не найден.")
|
||||
return
|
||||
}
|
||||
val updated = HumanBeingBuilder(inputManager).build()
|
||||
manager.update(id, updated)
|
||||
println("Элемент обновлён.")
|
||||
inputManager.print("Элемент обновлён.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.time.LocalDate
|
||||
import java.time.format.DateTimeParseException
|
||||
import java.util.Scanner
|
||||
import java.util.UUID
|
||||
import input.IOManager
|
||||
|
||||
/**
|
||||
* Менеджер файлового хранилища коллекции.
|
||||
@@ -33,6 +34,8 @@ class FileManager(private val filePath: String) {
|
||||
"hasToothpick,impactSpeed,soundtrackName,minutesOfWaiting,weaponType,carCool"
|
||||
}
|
||||
|
||||
private val console: IOManager = IOManager()
|
||||
|
||||
/**
|
||||
* Читает коллекцию из CSV-файла с помощью [Scanner].
|
||||
*
|
||||
@@ -45,12 +48,12 @@ class FileManager(private val filePath: String) {
|
||||
val file = File(filePath)
|
||||
|
||||
if (!file.exists()) {
|
||||
System.err.println("Файл '$filePath' не найден. Коллекция будет пустой.")
|
||||
console.printErrConsole("Файл '$filePath' не найден. Коллекция будет пустой.")
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
if (!file.canRead()) {
|
||||
System.err.println("Нет прав на чтение файла '$filePath'. Коллекция будет пустой.")
|
||||
console.printErrConsole("Нет прав на чтение файла '$filePath'. Коллекция будет пустой.")
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@@ -69,14 +72,14 @@ class FileManager(private val filePath: String) {
|
||||
|
||||
parseLine(line, lineNumber)
|
||||
?.let { result.add(it) }
|
||||
?: System.err.println("Строка $lineNumber пропущена: некорректные данные → '$line'")
|
||||
?: console.printErrConsole("Строка $lineNumber пропущена: некорректные данные → '$line'")
|
||||
}
|
||||
}
|
||||
} catch (e: FileNotFoundException) {
|
||||
System.err.println("Файл не найден во время чтения: ${e.message}")
|
||||
console.printErrConsole("Файл не найден во время чтения: ${e.message}")
|
||||
}
|
||||
|
||||
println("Загружено элементов: ${result.size} из файла '$filePath'")
|
||||
console.print("Загружено элементов: ${result.size} из файла '$filePath'")
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -91,7 +94,7 @@ class FileManager(private val filePath: String) {
|
||||
return try {
|
||||
val parts = line.split(DELIMITER, limit = 12)
|
||||
if (parts.size < 12) {
|
||||
System.err.println("Строка $lineNumber: ожидалось 12 полей, найдено ${parts.size}")
|
||||
console.printErrConsole("Строка $lineNumber: ожидалось 12 полей, найдено ${parts.size}")
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -122,13 +125,13 @@ class FileManager(private val filePath: String) {
|
||||
minutesOfWaiting = minutesOfWaiting, weaponType = weaponType, car = Car(carCool)
|
||||
)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
System.err.println("Строка $lineNumber — ошибка данных: ${e.message}")
|
||||
console.printErrConsole("Строка $lineNumber — ошибка данных: ${e.message}")
|
||||
null
|
||||
} catch (e: DateTimeParseException) {
|
||||
System.err.println("Строка $lineNumber — неверный формат даты: ${e.message}")
|
||||
console.printErrConsole("Строка $lineNumber — неверный формат даты: ${e.message}")
|
||||
null
|
||||
} catch (e: Exception) {
|
||||
System.err.println("Строка $lineNumber — неожиданная ошибка: ${e.message}")
|
||||
console.printErrConsole("Строка $lineNumber — неожиданная ошибка: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -143,7 +146,7 @@ class FileManager(private val filePath: String) {
|
||||
val file = File(filePath)
|
||||
|
||||
if (file.exists() && !file.canWrite()) {
|
||||
System.err.println("Нет прав на запись в файл '$filePath'.")
|
||||
console.printErrConsole("Нет прав на запись в файл '$filePath'.")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -156,13 +159,13 @@ class FileManager(private val filePath: String) {
|
||||
writer.write("\n")
|
||||
}
|
||||
}
|
||||
println("Коллекция сохранена в '$filePath' (${items.size} элементов).")
|
||||
console.print("Коллекция сохранена в '$filePath' (${items.size} элементов).")
|
||||
true
|
||||
} catch (e: SecurityException) {
|
||||
System.err.println("Отказано в доступе к файлу '$filePath': ${e.message}")
|
||||
console.printErrConsole("Отказано в доступе к файлу '$filePath': ${e.message}")
|
||||
false
|
||||
} catch (e: Exception) {
|
||||
System.err.println("Ошибка записи в файл: ${e.message}")
|
||||
console.printErrConsole("Ошибка записи в файл: ${e.message}")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import models.WeaponType
|
||||
*/
|
||||
class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
|
||||
private val console = IOManager()
|
||||
|
||||
/**
|
||||
* Запускает интерактивный ввод всех полей и возвращает готовый [HumanBeing].
|
||||
*
|
||||
@@ -62,7 +64,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
val input = inputManager.readLine()
|
||||
?: throw IllegalStateException("EOF")
|
||||
if (input.isNotBlank()) return input.trim()
|
||||
println("[Ошибка] Строка не может быть пустой.")
|
||||
console.print("[Ошибка] Строка не может быть пустой.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +79,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
try {
|
||||
return input.trim().toLong()
|
||||
} catch (e: NumberFormatException) {
|
||||
println("[Ошибка] Ожидается целое число (Long). Попробуйте снова.")
|
||||
console.print("[Ошибка] Ожидается целое число (Long). Попробуйте снова.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +95,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
try {
|
||||
return input.trim().toInt()
|
||||
} catch (e: NumberFormatException) {
|
||||
println("[Ошибка] Ожидается целое число (Int). Попробуйте снова.")
|
||||
console.print("[Ошибка] Ожидается целое число (Int). Попробуйте снова.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +111,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
try {
|
||||
return input.trim().toDouble()
|
||||
} catch (e: NumberFormatException) {
|
||||
println("[Ошибка] Ожидается число с плавающей точкой (Double). Попробуйте снова.")
|
||||
console.print("[Ошибка] Ожидается число с плавающей точкой (Double). Попробуйте снова.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +127,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
try {
|
||||
return input.trim().toFloat()
|
||||
} catch (e: NumberFormatException) {
|
||||
println("[Ошибка] Ожидается число (Float). Попробуйте снова.")
|
||||
console.print("[Ошибка] Ожидается число (Float). Попробуйте снова.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +143,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
when (input.trim().lowercase()) {
|
||||
"true" -> return true
|
||||
"false" -> return false
|
||||
else -> println("[Ошибка] Ожидается 'true' или 'false'. Попробуйте снова.")
|
||||
else -> console.print("[Ошибка] Ожидается 'true' или 'false'. Попробуйте снова.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +162,7 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
try {
|
||||
return WeaponType.valueOf(input.trim().uppercase())
|
||||
} catch (e: IllegalArgumentException) {
|
||||
println("[Ошибка] Неизвестный тип оружия '$input'. Допустимые значения: $constants")
|
||||
console.print("[Ошибка] Неизвестный тип оружия '$input'. Допустимые значения: $constants")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,6 +172,6 @@ class HumanBeingBuilder(private val inputManager: InputManager) {
|
||||
* В режиме скрипта приглашения не выводятся.
|
||||
*/
|
||||
private fun printPrompt(message: String) {
|
||||
if (inputManager.isInteractive) print(" > $message ")
|
||||
if (inputManager.isInteractive) console.print(" > $message ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package input
|
||||
import org.jline.reader.EndOfFileException
|
||||
import org.jline.reader.LineReaderBuilder
|
||||
import org.jline.reader.UserInterruptException
|
||||
import org.jline.reader.impl.completer.StringsCompleter
|
||||
import org.jline.terminal.TerminalBuilder
|
||||
|
||||
/**
|
||||
@@ -11,9 +10,14 @@ import org.jline.terminal.TerminalBuilder
|
||||
* Поддерживает историю команд (стрелки ↑↓), Tab-автодополнение,
|
||||
* корректную обработку Ctrl+C и Ctrl+D.
|
||||
*/
|
||||
class ConsoleInputManager() : InputManager {
|
||||
class IOManager() : InputManager {
|
||||
override val isInteractive = true
|
||||
|
||||
// сделать основной Scanner
|
||||
// при инициализации стандартный сканер добавляется
|
||||
// стек input, один (console) открыт постоянно
|
||||
// если файл - в стек кидается Scanner
|
||||
|
||||
private val terminal = TerminalBuilder.builder()
|
||||
.system(true)
|
||||
.build()
|
||||
@@ -36,6 +40,16 @@ class ConsoleInputManager() : InputManager {
|
||||
null // Ctrl+C
|
||||
}
|
||||
}
|
||||
|
||||
override fun print(text: String) {
|
||||
println(text)
|
||||
}
|
||||
|
||||
override fun printErrConsole(text: String) {
|
||||
System.err.println(text)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,16 @@ interface InputManager {
|
||||
*/
|
||||
fun readLine(): String?
|
||||
|
||||
/**
|
||||
* Выводит сообщение в консоль.
|
||||
*/
|
||||
fun print(text: String)
|
||||
|
||||
/**
|
||||
* Выводит ошибку в консоль.
|
||||
*/
|
||||
fun printErrConsole(text: String)
|
||||
|
||||
/**
|
||||
* Возвращает true если источник — интерактивная консоль.
|
||||
* Используется для управления выводом приглашений (prompt).
|
||||
|
||||
@@ -3,6 +3,8 @@ package input
|
||||
import java.io.File
|
||||
import java.util.Scanner
|
||||
|
||||
// удалить
|
||||
|
||||
/**
|
||||
* Реализация [InputManager] для чтения команд из файла.
|
||||
*
|
||||
@@ -18,4 +20,7 @@ class ScriptInputManager(filePath: String) : InputManager {
|
||||
|
||||
override fun readLine(): String? =
|
||||
if (scanner.hasNextLine()) scanner.nextLine() else null
|
||||
|
||||
override fun print(text: String) {}
|
||||
override fun printErrConsole(text: String) {}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ data class HumanBeing(
|
||||
|
||||
override fun hashCode(): Int = id.hashCode()
|
||||
|
||||
// убил на этот вывод часа 5-6. Зря я сюда полез
|
||||
// Зря я сюда полез
|
||||
/**
|
||||
* Красивое строковое представление для команды [show].
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package runner
|
||||
|
||||
import commands.Command
|
||||
import input.IOManager
|
||||
|
||||
/**
|
||||
* Инвокер команд.
|
||||
@@ -12,6 +13,7 @@ import commands.Command
|
||||
*/
|
||||
class CommandInvoker {
|
||||
|
||||
private val console = IOManager()
|
||||
private val commands = mutableMapOf<String, Command>()
|
||||
private val history = ArrayDeque<String>(12)
|
||||
|
||||
@@ -36,7 +38,7 @@ class CommandInvoker {
|
||||
|
||||
val command = commands[name]
|
||||
if (command == null) {
|
||||
println("Неизвестная команда: '$name'. Введите 'help' для справки.")
|
||||
console.print("Неизвестная команда: '$name'. Введите 'help' для справки.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,7 +46,7 @@ class CommandInvoker {
|
||||
try {
|
||||
command.execute(args)
|
||||
} catch (e: IllegalStateException) {
|
||||
println("[Ошибка выполнения] ${e.message}")
|
||||
console.print("[Ошибка выполнения] ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package runner
|
||||
|
||||
import java.io.File
|
||||
import java.util.Scanner
|
||||
import input.IOManager
|
||||
|
||||
/**
|
||||
* Очередь команд, собранных из файла-скрипта.
|
||||
@@ -18,6 +19,7 @@ class CommandQueue {
|
||||
private const val EXECUTE_SCRIPT_CMD = "execute_script"
|
||||
}
|
||||
|
||||
private val console = IOManager()
|
||||
private val queue = ArrayDeque<String>()
|
||||
|
||||
/** Количество команд в очереди. */
|
||||
@@ -41,17 +43,17 @@ class CommandQueue {
|
||||
) {
|
||||
// Защита от рекурсии
|
||||
if (filePath in visitedScripts) {
|
||||
println("[CommandQueue] Рекурсия обнаружена: '$filePath' уже в стеке, пропускаем.")
|
||||
console.print("[CommandQueue] Рекурсия обнаружена: '$filePath' уже в стеке, пропускаем.")
|
||||
return
|
||||
}
|
||||
|
||||
val file = File(filePath)
|
||||
if (!file.exists()) {
|
||||
println("[CommandQueue] Файл не найден: '$filePath'")
|
||||
console.print("[CommandQueue] Файл не найден: '$filePath'")
|
||||
return
|
||||
}
|
||||
if (!file.canRead()) {
|
||||
println("[CommandQueue] Нет прав на чтение: '$filePath'")
|
||||
console.print("[CommandQueue] Нет прав на чтение: '$filePath'")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -70,7 +72,7 @@ class CommandQueue {
|
||||
if (parts[0].lowercase() == EXECUTE_SCRIPT_CMD && parts.size > 1) {
|
||||
val nestedPath = File(parentDir, parts[1]).path
|
||||
if (!File(nestedPath).exists()) {
|
||||
println("[CommandQueue] Файл не найден: '$nestedPath'")
|
||||
console.print("[CommandQueue] Файл не найден: '$nestedPath'")
|
||||
return
|
||||
}
|
||||
loadFromScript(nestedPath, visitedScripts)
|
||||
|
||||
Reference in New Issue
Block a user