-
Notifications
You must be signed in to change notification settings - Fork 0
Добавлено консольное приложение "Заметки" с архивами и заметками #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| class App { | ||
| private val archives = mutableListOf<Archive>() | ||
| private var isRunning = true | ||
|
|
||
| fun start() { | ||
| while (isRunning) { | ||
| showArchiveMenu() | ||
|
|
||
| } | ||
| println("Программа завершена") | ||
| } | ||
|
|
||
| private fun showArchiveMenu() { | ||
| val menu = MenuScreen( | ||
| title = "Архивы", | ||
| items = archives.toList(), | ||
| onItemSelected = { archive -> showNotesMenu(archive) }, | ||
| onCreateNew = { createArchive() }, | ||
| onExit = { exit() } | ||
|
|
||
| ) | ||
| menu.show() | ||
| } | ||
|
|
||
| private fun createArchive() { | ||
| val result = CreateScreen("архив").show() | ||
| when (result) { | ||
| is CreateResult.ArchiveCreated -> { | ||
| archives.add(Archive(result.name)) | ||
| println("Архив \"${result.name}\" создан!") | ||
| } | ||
|
|
||
| is CreateResult.Cancelled -> { | ||
| println("Создание архива отменено") | ||
| } | ||
|
|
||
| else -> {} | ||
| } | ||
| } | ||
|
|
||
| private fun showNotesMenu(archive: Archive) { | ||
| var isInNotesMenu = true | ||
| while (isInNotesMenu) { | ||
| val menu = MenuScreen( | ||
| title = "Заметки в архиве \"${archive.name}\"", | ||
| items = archive.notes.toList(), | ||
| onItemSelected = { note -> showNote(note) }, | ||
| onCreateNew = { createNote(archive) }, | ||
| onExit = { isInNotesMenu = false }, | ||
|
|
||
| ) | ||
| menu.show() | ||
| } | ||
| } | ||
|
|
||
|
|
||
| private fun createNote(archive: Archive) { | ||
| val result = CreateScreen("заметки").show() | ||
|
|
||
| when (result) { | ||
| is CreateResult.NoteCreated -> { | ||
| archive.notes.add(Note(result.name, result.text)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лучше в классе Archive написать отдельный метод для создания заметки, чтобы изменяемый список |
||
| println("Заметка \"${result.name}\"создана!") | ||
| } | ||
|
|
||
| is CreateResult.Cancelled -> { | ||
| println("Создание заметки отменено") | ||
| } | ||
|
|
||
| else -> {} | ||
| } | ||
| } | ||
|
|
||
| private fun showNote(note: Note) { | ||
| ContentView(note).show() | ||
| } | ||
|
|
||
| private fun exit() { | ||
| isRunning = false | ||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| data class Archive( | ||
| val name: String, | ||
| val notes: MutableList<Note> = mutableListOf() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. В data классах не рекомендуется хранить мьютабельные данные (в данном случае MutableList), т.к. в многопоточных средах могут возникнуть проблемы с такими объектами, а именно с доступом к чтению и записи изменяемых полей. У data классов автоматически генерируется функция |
||
|
|
||
| ) { | ||
| override fun toString(): String = name | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import java.util.Scanner | ||
|
|
||
| class ContentView( | ||
| private val note: Note | ||
| ) { | ||
| fun show() { | ||
| println("\n===${note.nameNote}===") | ||
| println("-".repeat(40)) | ||
| println(note.textNote) | ||
| println("_".repeat(40)) | ||
| println("Нажмите Enter, что бы вернуться...") | ||
| Scanner(System.`in`).nextLine() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import java.util.Scanner | ||
|
|
||
|
|
||
| class CreateScreen( | ||
| private val itemType: String | ||
| ) { | ||
| companion object { | ||
| private val scanner = Scanner(System.`in`) | ||
| } | ||
|
|
||
| fun show(): CreateResult { | ||
| println("\nСоздание $itemType") | ||
| print("Введите название $itemType: ") | ||
| val name = scanner.nextLine().trim() | ||
| if (name.isEmpty()) { | ||
| println("Ошибка: название не может быть пустым") | ||
| return CreateResult.Cancelled | ||
| } | ||
| if (itemType == "заметки") { | ||
| print("Введите текст заметки: ") | ||
| val text = scanner.nextLine().trim() | ||
| if (text.isEmpty()) { | ||
| println("Ошибка: текст заметки не может быть пустым") | ||
| return CreateResult.Cancelled | ||
| } | ||
| return CreateResult.NoteCreated(name, text) | ||
| } | ||
| return CreateResult.ArchiveCreated(name) | ||
| } | ||
|
|
||
| } | ||
|
|
||
| sealed class CreateResult { | ||
| object Cancelled : CreateResult() | ||
| data class ArchiveCreated(val name: String) : CreateResult() | ||
| data class NoteCreated(val name: String, val text: String) : CreateResult() | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| fun main(args: Array<String>) { | ||
| println("Hello World!") | ||
| fun main() { | ||
| App().start() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| import java.util.Scanner | ||
|
|
||
|
|
||
| import kotlin.collections.toList | ||
|
|
||
| class MenuScreen<T>( | ||
| private val title: String, | ||
| private val items: List<T>, | ||
| private val onItemSelected: (T) -> Unit, | ||
| private val onCreateNew: () -> Unit, | ||
| private val onExit: () -> Unit | ||
| ) { | ||
| companion object { | ||
| private val scanner = Scanner(System.`in`) | ||
| } | ||
|
|
||
| fun show() { | ||
| val itemsSnapshot = items.toList() | ||
|
|
||
| while (true) { | ||
| println("\n=== $title ===") | ||
| if (itemsSnapshot.isEmpty()) { | ||
| println("Список пуст. Чтобы создать элемент, выберите пункт 'Создать'") | ||
| } else { | ||
| itemsSnapshot.forEachIndexed { index, item -> | ||
| println("${index + 1}. $item") | ||
| } | ||
| } | ||
| println("${itemsSnapshot.size + 1}. Создать") | ||
| println("0. Выход") | ||
| print("Выберите пункт (0-${itemsSnapshot.size + 1}): ") | ||
| val input = scanner.nextLine().trim() | ||
| val choice = input.toIntOrNull() | ||
| if (choice == null) { | ||
| println("Ошибка: введите цифру.") | ||
| continue | ||
| } | ||
| when (choice) { | ||
| 0 -> { | ||
| onExit() | ||
| return | ||
|
|
||
| } | ||
|
|
||
| in 1..itemsSnapshot.size -> { | ||
| onItemSelected(itemsSnapshot[choice - 1]) | ||
| return | ||
| } | ||
|
|
||
| itemsSnapshot.size + 1 -> { | ||
| onCreateNew() | ||
| return | ||
| } | ||
|
|
||
| else -> { | ||
| println("Ошибка: нет пункта с номером $choice.") | ||
| println("Доступные номера: 0-${itemsSnapshot.size + 1}") | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| data class Note( | ||
| val nameNote: String, | ||
| val textNote: String | ||
| ) { | ||
| override fun toString(): String = nameNote | ||
|
|
||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Всю папку .idea лучше сразу добавлять в gitignore - в ней хранятся локальные настройки разработчика, специфичные для проекта. После добавления важно не забыть удалить папку с репозитория