From 8d94a15e3e5174eafe81eeca001062edf3aa4593 Mon Sep 17 00:00:00 2001 From: xabko Date: Mon, 12 Jan 2026 13:47:00 +0300 Subject: [PATCH] Commit --- .idea/caches/deviceStreaming.xml | 1258 +++++++++++++++++ .idea/deviceManager.xml | 13 + .idea/markdown.xml | 8 + .idea/misc.xml | 2 +- src/main/kotlin/Main.kt | 18 +- src/main/kotlin/menu/Menu.kt | 50 + src/main/kotlin/menu/MenuItem.kt | 7 + src/main/kotlin/menu/MenuNavigator.kt | 37 + src/main/kotlin/models/Archive.kt | 15 + src/main/kotlin/models/Note.kt | 7 + .../kotlin/screens/ArchiveCreationScreen.kt | 52 + .../kotlin/screens/ArchiveSelectionScreen.kt | 48 + src/main/kotlin/screens/NoteCreationScreen.kt | 71 + .../kotlin/screens/NoteSelectionScreen.kt | 43 + src/main/kotlin/screens/NoteViewScreen.kt | 39 + 15 files changed, 1665 insertions(+), 3 deletions(-) create mode 100644 .idea/caches/deviceStreaming.xml create mode 100644 .idea/deviceManager.xml create mode 100644 .idea/markdown.xml create mode 100644 src/main/kotlin/menu/Menu.kt create mode 100644 src/main/kotlin/menu/MenuItem.kt create mode 100644 src/main/kotlin/menu/MenuNavigator.kt create mode 100644 src/main/kotlin/models/Archive.kt create mode 100644 src/main/kotlin/models/Note.kt create mode 100644 src/main/kotlin/screens/ArchiveCreationScreen.kt create mode 100644 src/main/kotlin/screens/ArchiveSelectionScreen.kt create mode 100644 src/main/kotlin/screens/NoteCreationScreen.kt create mode 100644 src/main/kotlin/screens/NoteSelectionScreen.kt create mode 100644 src/main/kotlin/screens/NoteViewScreen.kt diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml new file mode 100644 index 00000000..51d2b618 --- /dev/null +++ b/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1258 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml new file mode 100644 index 00000000..91f95584 --- /dev/null +++ b/.idea/deviceManager.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/.idea/markdown.xml b/.idea/markdown.xml new file mode 100644 index 00000000..c61ea334 --- /dev/null +++ b/.idea/markdown.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9c8e7400..2bfdeda2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index aade54c5..4b751e19 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -1,3 +1,17 @@ -fun main(args: Array) { - println("Hello World!") +import menu.MenuNavigator +import models.Archive +import screens.ArchiveSelectionScreen + +fun main() { + println("Добро пожаловать в приложение Заметки!") + println("Версия 1.0") + + + val archives = mutableListOf() + + + val archiveSelectionScreen = ArchiveSelectionScreen(archives) + + + MenuNavigator.startWith(archiveSelectionScreen) } \ No newline at end of file diff --git a/src/main/kotlin/menu/Menu.kt b/src/main/kotlin/menu/Menu.kt new file mode 100644 index 00000000..ac17ca4d --- /dev/null +++ b/src/main/kotlin/menu/Menu.kt @@ -0,0 +1,50 @@ +package menu + +import java.util.Scanner + +abstract class Menu { + protected val scanner = Scanner(System.`in`) + protected val menuItems = mutableListOf() + + protected fun addMenuItem(item: MenuItem) { + menuItems.add(item) + } + + protected fun displayMenu(header: String) { + println("\n${"=".repeat(50)}") + println(header) + println("${"=".repeat(50)}") + + menuItems.sortedBy { it.index }.forEach { item -> + println("${item.index}. ${item.title}") + } + + println("${"=".repeat(50)}") + print("Выберите пункт меню: ") + } + + open fun show() { + while (true) { + displayMenu(getMenuHeader()) + + try { + val choice = scanner.nextLine().toInt() + val menuItem = menuItems.find { it.index == choice } + + if (menuItem != null) { + menuItem.action() + if (shouldExitAfterAction(choice)) { + break + } + } else { + println("Ошибка: выбран неверный пункт меню. Попробуйте снова.") + } + } catch (e: NumberFormatException) { + println("Ошибка: введите номер пункта меню.") + } + } + } + + protected abstract fun getMenuHeader(): String + protected abstract fun shouldExitAfterAction(choice: Int): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/menu/MenuItem.kt b/src/main/kotlin/menu/MenuItem.kt new file mode 100644 index 00000000..45eb5672 --- /dev/null +++ b/src/main/kotlin/menu/MenuItem.kt @@ -0,0 +1,7 @@ +package menu + +data class MenuItem( + val index: Int, + val title: String, + val action: () -> Unit +) \ No newline at end of file diff --git a/src/main/kotlin/menu/MenuNavigator.kt b/src/main/kotlin/menu/MenuNavigator.kt new file mode 100644 index 00000000..596472c5 --- /dev/null +++ b/src/main/kotlin/menu/MenuNavigator.kt @@ -0,0 +1,37 @@ +package menu + +object MenuNavigator { + private val screenStack = mutableListOf() + + fun pushScreen(screen: Menu) { + screenStack.add(screen) + } + + fun popScreen() { + if (screenStack.isNotEmpty()) { + screenStack.removeLast() + } + } + + fun startWith(screen: Menu) { + screenStack.clear() + pushScreen(screen) + showCurrentScreen() + } + + fun navigateTo(screen: Menu) { + pushScreen(screen) + showCurrentScreen() + } + + fun back() { + popScreen() + if (screenStack.isNotEmpty()) { + showCurrentScreen() + } + } + + private fun showCurrentScreen() { + screenStack.lastOrNull()?.show() + } +} \ No newline at end of file diff --git a/src/main/kotlin/models/Archive.kt b/src/main/kotlin/models/Archive.kt new file mode 100644 index 00000000..67a64898 --- /dev/null +++ b/src/main/kotlin/models/Archive.kt @@ -0,0 +1,15 @@ +package models + +class Archive(val name: String) { + private val noteStorage = mutableListOf() + + fun addNote(note: Note) { + noteStorage.add(note) + } + + + fun getNotes(): List = noteStorage.toList() + + + fun getNotesCount(): Int = noteStorage.size +} \ No newline at end of file diff --git a/src/main/kotlin/models/Note.kt b/src/main/kotlin/models/Note.kt new file mode 100644 index 00000000..023f2723 --- /dev/null +++ b/src/main/kotlin/models/Note.kt @@ -0,0 +1,7 @@ +package models + +data class Note( + val title: String, + val content: String, + val createdAt: Long = System.currentTimeMillis() +) \ No newline at end of file diff --git a/src/main/kotlin/screens/ArchiveCreationScreen.kt b/src/main/kotlin/screens/ArchiveCreationScreen.kt new file mode 100644 index 00000000..97b0e4aa --- /dev/null +++ b/src/main/kotlin/screens/ArchiveCreationScreen.kt @@ -0,0 +1,52 @@ +package screens + +import models.Archive +import menu.Menu +import menu.MenuNavigator +import java.util.Scanner + +class ArchiveCreationScreen(private val archives: MutableList) : Menu() { + + init { + + menuItems.add(menu.MenuItem(1, "Вернуться назад") {}) + } + + override fun show() { + println("\n${"=".repeat(50)}") + println("СОЗДАНИЕ АРХИВА") + println("${"=".repeat(50)}") + + var archiveName: String + val scanner = Scanner(System.`in`) + + while (true) { + print("Введите название архива: ") + archiveName = scanner.nextLine().trim() + + if (archiveName.isEmpty()) { + println("Ошибка: название архива не может быть пустым.") + continue + } + + if (archives.any { it.name == archiveName }) { + println("Ошибка: архив с таким названием уже существует.") + continue + } + + break + } + + val archive = Archive(archiveName) + archives.add(archive) + println("Архив '$archiveName' успешно создан!") + + + Thread.sleep(1000) + MenuNavigator.back() + } + + override fun getMenuHeader(): String = "Создание архива" + + override fun shouldExitAfterAction(choice: Int): Boolean = true +} \ No newline at end of file diff --git a/src/main/kotlin/screens/ArchiveSelectionScreen.kt b/src/main/kotlin/screens/ArchiveSelectionScreen.kt new file mode 100644 index 00000000..83974b69 --- /dev/null +++ b/src/main/kotlin/screens/ArchiveSelectionScreen.kt @@ -0,0 +1,48 @@ +package screens + +import models.Archive +import menu.Menu +import menu.MenuItem +import menu.MenuNavigator + +class ArchiveSelectionScreen(private val archives: MutableList) : Menu() { + + override fun show() { + menuItems.clear() + initializeMenu() + super.show() + } + + private fun initializeMenu() { + // Пункт для создания нового архива + addMenuItem(MenuItem(0, "Создать архив") { + MenuNavigator.navigateTo(ArchiveCreationScreen(archives)) + }) + + // Пункты для существующих архивов + archives.forEachIndexed { index, archive -> + addMenuItem(MenuItem(index + 1, archive.name) { + MenuNavigator.navigateTo(NoteSelectionScreen(archive)) + }) + } + + // Пункт для выхода + val exitIndex = archives.size + 1 + addMenuItem(MenuItem(exitIndex, "Выход") { + println("До свидания!") + System.exit(0) + }) + } + + override fun getMenuHeader(): String { + return if (archives.isEmpty()) { + "Список архивов (пока пуст)" + } else { + "Список архивов:" + } + } + + override fun shouldExitAfterAction(choice: Int): Boolean { + return false + } +} \ No newline at end of file diff --git a/src/main/kotlin/screens/NoteCreationScreen.kt b/src/main/kotlin/screens/NoteCreationScreen.kt new file mode 100644 index 00000000..3ed25fb3 --- /dev/null +++ b/src/main/kotlin/screens/NoteCreationScreen.kt @@ -0,0 +1,71 @@ +package screens + +import models.Note +import models.Archive +import menu.Menu +import menu.MenuItem +import menu.MenuNavigator +import java.util.Scanner + +class NoteCreationScreen(private val archive: Archive) : Menu() { + + init { + menuItems.add(MenuItem(1, "Вернуться назад") {}) + } + + override fun show() { + println("\n${"=".repeat(50)}") + println("СОЗДАНИЕ ЗАМЕТКИ") + println("Архив: ${archive.name}") + println("${"=".repeat(50)}") + + val scanner = Scanner(System.`in`) + + // Ввод названия заметки + var title: String + while (true) { + print("Введите название заметки: ") + title = scanner.nextLine().trim() + + if (title.isEmpty()) { + println("Ошибка: название заметки не может быть пустым.") + continue + } + + break + } + + + println("Введите текст заметки (введите пустую строку для завершения):") + val lines = mutableListOf() + + while (true) { + print("> ") + val line = scanner.nextLine() + if (line.trim().isEmpty() && lines.isNotEmpty()) { + break + } + if (line.trim().isNotEmpty()) { + lines.add(line) + } + } + + val content = lines.joinToString("\n") + + if (content.trim().isEmpty()) { + println("Ошибка: текст заметки не может быть пустым.") + } else { + val note = Note(title, content) + archive.addNote(note) + println("Заметка '$title' успешно создана!") + } + + + Thread.sleep(1000) + MenuNavigator.back() + } + + override fun getMenuHeader(): String = "Создание заметки" + + override fun shouldExitAfterAction(choice: Int): Boolean = true +} \ No newline at end of file diff --git a/src/main/kotlin/screens/NoteSelectionScreen.kt b/src/main/kotlin/screens/NoteSelectionScreen.kt new file mode 100644 index 00000000..97fd49a6 --- /dev/null +++ b/src/main/kotlin/screens/NoteSelectionScreen.kt @@ -0,0 +1,43 @@ +package screens + +import models.Archive +import menu.Menu +import menu.MenuItem +import menu.MenuNavigator + +class NoteSelectionScreen(private val archive: Archive) : Menu() { + + override fun show() { + menuItems.clear() + initializeMenu() + super.show() + } + + private fun initializeMenu() { + // Пункт для создания новой заметки + addMenuItem(MenuItem(0, "Создать заметку") { + MenuNavigator.navigateTo(NoteCreationScreen(archive)) + }) + + + archive.getNotes().forEachIndexed { index, note -> + addMenuItem(MenuItem(index + 1, note.title) { + MenuNavigator.navigateTo(NoteViewScreen(note)) + }) + } + + + val backIndex = archive.getNotes().size + 1 + addMenuItem(MenuItem(backIndex, "Назад к архивам") { + MenuNavigator.back() + }) + } + + override fun getMenuHeader(): String { + return "Архив: ${archive.name}\nСписок заметок:" + } + + override fun shouldExitAfterAction(choice: Int): Boolean { + return false + } +} \ No newline at end of file diff --git a/src/main/kotlin/screens/NoteViewScreen.kt b/src/main/kotlin/screens/NoteViewScreen.kt new file mode 100644 index 00000000..7c74913d --- /dev/null +++ b/src/main/kotlin/screens/NoteViewScreen.kt @@ -0,0 +1,39 @@ +package screens + +import models.Note +import menu.Menu +import menu.MenuItem +import menu.MenuNavigator +import java.text.SimpleDateFormat +import java.util.* + +class NoteViewScreen(private val note: Note) : Menu() { + + init { + menuItems.add(MenuItem(1, "Назад к списку заметок") { + MenuNavigator.back() + }) + } + + override fun show() { + println("\n${"=".repeat(50)}") + println("ЗАМЕТКА: ${note.title}") + println("${"=".repeat(50)}") + + val dateFormat = SimpleDateFormat("dd.MM.yyyy HH:mm") + val dateString = dateFormat.format(Date(note.createdAt)) + println("Создано: $dateString") + println("-".repeat(50)) + println(note.content) + println("${"=".repeat(50)}") + + println("\nНажмите Enter, чтобы вернуться назад...") + Scanner(System.`in`).nextLine() + + MenuNavigator.back() + } + + override fun getMenuHeader(): String = "Просмотр заметки" + + override fun shouldExitAfterAction(choice: Int): Boolean = true +} \ No newline at end of file