diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..fb50116 --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..a462aa3 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + Taskmanager + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..a4138e2 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,126 @@ +import java.util.Scanner; + +//アプリ起動クラス +//画面制御用 +//実際の処理はTaskManagerへ委譲する +public class Main { + + public static void main(String[] args) { + + //キーボード入力用 + Scanner sc = new Scanner(System.in); + //タスク管理クラス生成 + TaskManager manager = new TaskManager(); + //起動時にCSV読込 + manager.loadTasks(); + //メニュー処理開始 + showMenu(sc, manager); + + sc.close(); + + } + + // メニュー処理 + // 4が入力されるまでループ + public static void showMenu(Scanner sc, TaskManager manager) { + + //メニュー番号 + int menu = 0; + + while (menu != 5) { + + //タスク一覧表示 + manager.displayTasks(); + //メニュー表示 + displayMenu(); + + try { + + //入力値を数値へ変換 + //数字以外の場合は再入力指示 + menu =Integer.parseInt(sc.nextLine()); + //メニュー実行 + executeMenu(menu, sc, manager); + + } catch (NumberFormatException e) { + + //1~4が入力された場合 + inputError(sc); + + } + } + } + + //メニュー表示 + public static void displayMenu() { + + //行間調整 + System.out.println(); + System.out.print("[1] タスク追加 "); + System.out.print("[2] 完了/未完了の切り替え "); + System.out.print("[3] 削除 "); + System.out.print("[4] ソート "); + System.out.println("[5] 終了"); + + System.out.print("番号を入力してください > "); + + } + + //メニュー実行 + //入力された番号に応じて処理を呼び出す + public static void executeMenu(int menu, Scanner sc, TaskManager manager) { + + switch (menu) { + + case 1: + //タスク追加 + manager.addTask(sc); + + break; + + case 2: + //状態切替 + manager.changeStatus(sc); + + break; + + case 3: + //タスク削除 + manager.deleteTask(sc); + + break; + + case 4: + + manager.sortTasks(sc); + + break; + + case 5: + + break; + + default: + + // 1~5以外の数値入力 + inputError(sc); + + break; + + } + + } + + // 入力エラー + // Enter入力後にメニューへ戻る + public static void inputError(Scanner sc) { + + System.out.println(); + System.out.println( + "正しい番号を入力してください。Enterキーを押してください。"); + + sc.nextLine(); + + } + +} \ No newline at end of file diff --git a/src/Task.java b/src/Task.java new file mode 100644 index 0000000..0fed1ff --- /dev/null +++ b/src/Task.java @@ -0,0 +1,64 @@ + //タスク情報管理用クラス + //カプセル化のためフィールドはprivate + //値の取得や変更はgetter/setterを利用する + +public class Task { + //タスクID + private int id; + //タスク名 + private String taskName; + //完了状態 + private boolean completed; + //期限 + private String deadline; + //優先度 + private int priority; + + //コンストラクタ + //タスク生成時に初期値を設定 + + public Task(int id, String taskName, boolean completed, String deadline, int priority) { + this.id = id; + this.taskName = taskName; + this.completed = completed; + this.deadline = deadline; + this.priority = priority; + } + + //ID取得 + //ゲッター + public int getId() { + return id; + } + + //タスク名取得 + //ゲッター + public String getTaskName() { + return taskName; + } + + //完了状態取得 + //ゲッター + public boolean isCompleted() { + return completed; + } + + //完了状態切り替え時に使用 + //セッター + public void setCompleted(boolean completed) { + this.completed = completed; + } + + //期限取得 + //ゲッター + public String getDeadline() { + return deadline; + } + + //優先度取得 + //ゲッター + public int getPriority() { + return priority; + } + +} diff --git a/src/TaskManager.java b/src/TaskManager.java new file mode 100644 index 0000000..02ced39 --- /dev/null +++ b/src/TaskManager.java @@ -0,0 +1,520 @@ +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Scanner; + +//タスク管理クラス +//タスクの登録・表示・削除・状態変更 +//CSVの読込・保存 +public class TaskManager { + // CSVファイル保存先 + public static String Path = + "C:\\Users\\石原 叶大\\Documents\\development-taskmanager\\タスク管理システム実行例_石原\\tasks.csv"; + + //タスク一覧 + //タスク数が増減するのでArrayListを使用 + private ArrayList tasks = new ArrayList(); + //CSV読込 + //CSVデータをArrayListへ格納する + public void loadTasks() { + try { + BufferedReader br = new BufferedReader(new FileReader(Path)); + + String line; + //1行ずつ読み込むループ + while ((line = br.readLine()) != null) { + //カンマ区切りで分割 + String[] data = line.split(","); + + if (data.length == 5) { + int id = Integer.parseInt(data[0]); + String taskName = data[1]; + boolean completed = Boolean.parseBoolean(data[2]); + String deadline = data[3]; + int priority = Integer.parseInt(data[4]); + + Task task = new Task(id, taskName, completed, deadline, priority); + tasks.add(task); + } + } + br.close(); + + } catch (IOException e) { + System.out.println("CSVファイルが存在しないため新規作成します"); + } + } + + //CSV保存 + //ArrayList内のデータをCSVへ保存 + + public void saveTasks() { + try { + FileWriter fw = new FileWriter(Path); + + //全件保存 + for (Task task : tasks) { + fw.write( + task.getId() + "," + + task.getTaskName() + "," + + task.isCompleted() + "," + + task.getDeadline() + "," + + task.getPriority() + + "\n");//改行用 + } + fw.close(); + + } catch (IOException e) { + System.out.println("保存に失敗しました"); + } + } + + //文字色 + public static String Red = "\u001B[31m"; + public static String Yellow = "\u001B[33m"; + public static String Blue = "\u001B[36m"; + public static String Gray = "\u001B[90m"; + public static String Reset = "\u001B[0m"; + + //タスク一覧表示 + public void displayTasks() { + + System.out.println("=========================================================="); + System.out.println(" Task Manager"); + System.out.println("=========================================================="); + System.out.println("ID | 状態 | 優先度 | 期限 | タスク名"); + System.out.println("----------------------------------------------------------"); + + if (tasks.isEmpty()) { + System.out.println("登録されているタスクはありません。"); + return; + } + + //拡張for文 + //ArrayListからタスクを1件ずつ取得 + for (Task task : tasks) { + String status; + // TRUE/FALSEを表示用文字へ変換 + if (task.isCompleted()) { + status = "[x] 完了 "; + } else { + status = "[ ] 未完了"; + } + String priorityText = ""; + + //優先度変換 + switch (task.getPriority()) { + + case 1: + priorityText = "低 "; + break; + + case 2: + priorityText = "中 "; + break; + + case 3: + priorityText = "高 "; + break; + + } + + if (!task.isCompleted()) { + + switch (task.getPriority()) { + + case 1: + priorityText = Blue + priorityText + Reset; + break; + + case 2: + priorityText = Yellow + priorityText + Reset; + break; + + case 3: + priorityText = Red + priorityText + Reset; + break; + } + } + + String gray = + padRight(String.valueOf(task.getId()), 3) + + "| " + + padRight(status, 10) + + "| " + + priorityText + + "| " + + padRight(task.getDeadline(), 11) + + "| " + + task.getTaskName(); + + if (task.isCompleted()) { + + System.out.println( + Gray + gray + Reset); + + } else { + + System.out.println(gray); + + } + } + } + //タスク追加 + //入力内容からタスクを作成 + public void addTask(Scanner sc) { + //行間調整用 + System.out.println(); + // タスク名入力 + System.out.print("タスク名を入力:"); + String taskName = sc.nextLine(); + + //期限入力 + System.out.print( + "期限を入力(例:2026/09/20) [未入力で今日]:"); + + String deadline = + sc.nextLine(); + + //未入力なら今日の日付 + if (deadline.isEmpty()) { + deadline = LocalDate.now().toString().replace("-", "/"); + + } else { + try { + //入力値を日付へ変換 + LocalDate inputDate = LocalDate.parse(deadline.replace("/", "-")); + + //過去日付なら処理中断 + if (inputDate.isBefore(LocalDate.now())) { + System.out.println("過去の日付は入力できません。"); + + pause(sc); + return; + } + + //保存形式をYYYY/MM/DDに統一 + deadline =inputDate.toString().replace("-", "/"); + + } catch (Exception e) { + System.out.println("正しい日付を入力してください。(YYYY/MM/DD) 例:2026/01/01"); + + pause(sc); + return; + } + } + + //優先度入力 + System.out.print( "優先度(1:低 2:中 3:高) [デフォルト:2]:"); + + String input = sc.nextLine(); + + //未入力なら中 + int priority = 2; + if (!input.isEmpty()) { + + priority = Integer.parseInt(input); + + //1~3以外なら中断 + if (priority < 1 || priority > 3) { + return; + } + } + + //新規ID + int id = 1; + if (!tasks.isEmpty()) { + id = tasks.get(tasks.size() - 1).getId() + 1; + } + + //タスク生成 + Task task = new Task(id, taskName, false, deadline, priority); + + //一覧へ追加 + tasks.add(task); + + //CSV保存 + saveTasks(); + + } + + //完了・未完了切替 + public void changeStatus(Scanner sc) { + //行間調整 + System.out.println(); + System.out.print("状態を変更するタスクIDを入力:"); + + int targetId = Integer.parseInt(sc.nextLine()); + + boolean found = false; + for (Task task : tasks) { + if (task.getId() == targetId) { + + //true・false変換 + + task.setCompleted(!task.isCompleted()); + found = true; + + break; + + } + + } + + if (found) { + saveTasks(); + System.out.println("状態を切り替えました。"); + + } else { + System.out.println( + "そのIDのタスクはみつかりませんでした。"); + + } + + pause(sc); + + } + + //タスク削除 + //指定IDのタスクを削除する + public void deleteTask(Scanner sc) { + //行間調整 + System.out.println(); + System.out.print("削除するタスクIDを入力:"); + + int targetId = Integer.parseInt(sc.nextLine()); + + boolean found = false; + + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i).getId() == targetId) { + tasks.remove(i); + found = true; + + break; + } + } + + if (found) { + saveTasks(); + System.out.println("タスクを削除しました。"); + + } else { + System.out.println("そのIDのタスクは見つかりませんでした。"); + + } + + pause(sc); + + } + //タスク名種別判定 + //タスク名の先頭文字からソート用に番号を返す + //英語→1、ひらがな→2、カタカナ→3、数字→4 + private int getTaskNameCategory(String taskName) { + + if (taskName.isEmpty()) { + return 5; + } + + char c = taskName.charAt(0); + + //英字 + if ((c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z')) { + return 1; + } + + //ひらがな + if (c >= 'あ' && c <= 'ん') { + return 2; + } + + //カタカナ + if (c >= 'ア' && c <= 'ン') { + return 3; + } + + //数字 + if (c >= '0' && c <= '9') { + return 4; + + } + + return 5; + + } + + //ソート + //指定項目を昇順または降順で並び替える + public void sortTasks(Scanner sc) { + + System.out.println("[1] ID"); + System.out.println("[2] 状態"); + System.out.println("[3] 優先度"); + System.out.println("[4] 期限"); + System.out.println("[5] タスク名"); + + System.out.print("どの項目をソートしますか > "); + + int type; + try { + type = Integer.parseInt(sc.nextLine()); + + } catch (NumberFormatException e) { + Main.inputError(sc); + + return; + } + + //入力チェック + //1~5以外の場合はメニューへ戻る + if (type < 1 || type > 5) { + Main.inputError(sc); + + return; + } + //行間調整 + System.out.println(); + System.out.println("[1] 昇順"); + System.out.println("[2] 降順"); + + System.out.print("並び順を選択してください > "); + + int order; + try { + order = Integer.parseInt(sc.nextLine()); + + } catch (NumberFormatException e) { + Main.inputError(sc); + + return; + } + + //入力チェック + //1または2以外の場合はメニューへ戻る + if (order < 1 || order > 2) { + Main.inputError(sc); + + return; + } + + //true=昇順 false=降順 + boolean ascending = order == 1; + + switch (type) { + + //IDソート + case 1: + if (ascending) { + tasks.sort(Comparator.comparingInt(Task::getId)); + + } else { + tasks.sort(Comparator.comparingInt(Task::getId).reversed()); + } + + break; + + //状態ソート + case 2: + if (ascending) { + tasks.sort(Comparator.comparing(Task::isCompleted)); + + } else { + tasks.sort(Comparator.comparing(Task::isCompleted).reversed()); + } + + break; + + //優先度ソート + case 3: + if (ascending) { + tasks.sort(Comparator.comparingInt(Task::getPriority)); + + } else { + tasks.sort(Comparator.comparingInt(Task::getPriority).reversed()); + + } + + break; + + //期限ソート + case 4: + if (ascending) { + tasks.sort(Comparator.comparing(Task::getDeadline)); + + } else { + tasks.sort(Comparator.comparing(Task::getDeadline).reversed()); + + } + + break; + + //タスク名ソート + case 5: + if (ascending) { + tasks.sort((task1, task2) -> { + int category1 =getTaskNameCategory(task1.getTaskName()); + int category2 =getTaskNameCategory(task2.getTaskName()); + + //文字種別比較 + if (category1 != category2) { + + return category1 - category2; + + } + + //同じ文字種別なら名前比較 + return task1.getTaskName().compareTo(task2.getTaskName()); + + }); + + } else { + tasks.sort((task1, task2) -> { + + int category1 = getTaskNameCategory(task1.getTaskName()); + + int category2 = getTaskNameCategory(task2.getTaskName()); + + //文字種別比較 + if (category1 != category2) { + + return category2 - category1; + + } + + //同じ文字種別なら逆順比較 + return task2.getTaskName().compareTo(task1.getTaskName()); + + }); + } + break; + } + + pause(sc); + + } + //指定文字数まで空白を追加 + //一覧表示の列を揃えるために利用 + public String padRight( + String text, + int length) { + + while (text.length() < length) { + text += " "; + } + return text; + + } + + //Enter待機 + public void pause(Scanner sc) { + System.out.println("Enterキーを押してください。"); + + sc.nextLine(); + + } + +} \ No newline at end of file diff --git a/タスク管理システム実行例_石原/TaskManager.exe b/タスク管理システム実行例_石原/TaskManager.exe new file mode 100644 index 0000000..9782d56 Binary files /dev/null and b/タスク管理システム実行例_石原/TaskManager.exe differ diff --git a/タスク管理システム実行例_石原/tasks.csv b/タスク管理システム実行例_石原/tasks.csv new file mode 100644 index 0000000..a7a1d67 --- /dev/null +++ b/タスク管理システム実行例_石原/tasks.csv @@ -0,0 +1,13 @@ +6,test,false,2026/10/23,2 +7,test,true,2026/10/23,2 +8,test2,false,2026/12/12,1 +9,test3,false,2026/10/23,2 +10,test,false,2026-12-12,2 +11,1,false,2026/12/12,1 +12,test,false,2026/12/12,2 +13,test,false,2026/10/23,3 +14,1,false,2026/10/23,2 +14,test,false,2026/10/23,2 +15,2,false,2026/10/23,2 +16,ぱぴこ,false,2026/10/23,2 +17,パピコ,false,2026/10/23,2