From 008a5f9ff5b9409189e37a95523acfc3be6186ba Mon Sep 17 00:00:00 2001 From: Hyewon Date: Thu, 11 Dec 2025 22:22:43 +0900 Subject: [PATCH 1/2] Make Result View --- src/main/java/com/unitime/App.java | 67 +++++++-- src/main/java/com/unitime/UI/ResultView.java | 130 ++++++++++++++++++ src/main/java/com/unitime/feature/Course.java | 2 +- 3 files changed, 189 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/unitime/App.java b/src/main/java/com/unitime/App.java index ca48bc0..56b1e31 100644 --- a/src/main/java/com/unitime/App.java +++ b/src/main/java/com/unitime/App.java @@ -1,13 +1,62 @@ package com.unitime; -/** - * Hello world! - * - */ -public class App -{ - public static void main( String[] args ) - { - System.out.println( "Hello World!" ); +import java.util.List; +import java.util.Scanner; + +// 지금까지 만든 파일들(패키지) 가져오기 +import com.unitime.UI.ResultView; +import com.unitime.feature.InputHandler; +import com.unitime.feature.Course; +import com.unitime.algorthm.Scheduler; // 패키지명 오타(algorthm) 주의! 수정했다면 algorithm으로 변경하세요. + +public class App { + public static void main( String[] args ) { + // 1. 프로그램 전체에서 쓸 스캐너 생성 + Scanner sc = new Scanner(System.in); + + // 2. 인트로 화면 보여주기 (IntroScreen 코드가 있다면 주석 해제) + // IntroScreen.show(); + System.out.println("\n=== Welcome to UniTime-Solver! ==="); // 임시 인트로 + System.out.println("Press [ENTER] to start..."); + sc.nextLine(); + + // 3. 메인 무한 루프 (edit을 누르면 다시 여기로 돌아옴) + while(true) { + + // --- [STEP 1] 사용자 입력 받기 --- + // InputHandler가 생성되면서 사용자에게 과목 입력을 받음 + InputHandler inputHandler = new InputHandler(); + + // --- [STEP 2] 시간표 짜기 (알고리즘 가동) --- + System.out.println("\n[Algorithm] Generating optimal timetables..."); + Scheduler scheduler = new Scheduler(); + List> results = scheduler.schedule( + inputHandler.getMandatoryList(), + inputHandler.getOptionalList(), + inputHandler.getMaxCredit() + ); + + // --- [STEP 3] 결과 보여주기 (View Loop) --- + int currentIndex = 0; + boolean viewingResults = true; + + while (viewingResults) { + // ResultView를 불러서 화면을 보여주고, 사용자의 선택("next" or "edit")을 받아옴 + String command = ResultView.printBatchAndGetInput(results, currentIndex, sc); + + if (command.equals("next")) { + // 다음 페이지로 이동 로직 + if (currentIndex + 5 < results.size()) { + currentIndex += 5; + } else { + // 더 이상 없는데 next 누른 경우 (ResultView에서 이미 메시지 띄웠으므로 패스) + } + } + else if (command.equals("edit")) { + // 입력 화면으로 돌아가기 위해 내부 루프 탈출 -> 외부 while문의 처음으로 이동 + viewingResults = false; + } + } + } } } diff --git a/src/main/java/com/unitime/UI/ResultView.java b/src/main/java/com/unitime/UI/ResultView.java index e69de29..b30ca77 100644 --- a/src/main/java/com/unitime/UI/ResultView.java +++ b/src/main/java/com/unitime/UI/ResultView.java @@ -0,0 +1,130 @@ +package com.unitime.UI; + +import java.util.Collections; +import java.util.List; +import java.util.Scanner; +import com.unitime.feature.Course; + +public class ResultView { + + // ============================================================= + // 1. Style constant (ANSI Code) + // ============================================================= + public static final String RESET = "\u001B[0m"; + public static final String RED = "\u001B[31m"; + public static final String GREEN = "\u001B[32m"; + public static final String YELLOW = "\u001B[33m"; + public static final String BLUE = "\u001B[34m"; + public static final String PURPLE = "\u001B[35m"; + public static final String CYAN = "\u001B[36m"; + public static final String BLACK = "\u001B[30m"; + public static final String BOLD = "\u001B[1m"; + + private static final int BATCH_SIZE = 5; + + /** + * [Core Method] + * Displays the current batch of timetables and returns the user's selection (next/edit). + * Note: This method is purely for display and input retrieval; it does not contain pagination logic. + * * @param allSchedules The complete list of generated timetables. + * @param currentIndex The starting index for the current batch (managed externally by the controller). + * @param scanner The Scanner instance for receiving user input. + * @return The command entered by the user (e.g., "next" or "edit"). + */ + public static String printBatchAndGetInput(List> allSchedules, int currentIndex, Scanner scanner) { + + // 1. Exception for no timetable + if (allSchedules == null || allSchedules.isEmpty()) { + System.out.println(RED + "\n( T_T ) No timetables found." + RESET); + return "edit"; // Instantly go to "edit" + } + + int totalSize = allSchedules.size(); + int endIndex = Math.min(currentIndex + BATCH_SIZE, totalSize); + boolean hasNext = (endIndex < totalSize); + + // 2. Print Header (Print in each new page) + System.out.println(CYAN + "\n========================= Timetable =========================" + RESET); + System.out.println(YELLOW + BOLD + " (*'▽ '*) Found " + totalSize + " timetables! Showing " + (currentIndex + 1) + "~" + endIndex + " (*'▽ '*)" + RESET); + System.out.println(CYAN + "=============================================================" + RESET); + + // 3. Print 5 timetables + for (int i = currentIndex; i < endIndex; i++) { + printSingleSchedule(i + 1, allSchedules.get(i)); + } + + // 4. Print Neviagtion menu + printNavigationMenu(hasNext); + + // 5. Get user input and return + System.out.print("Your choice > "); + String input = scanner.nextLine().trim(); + + // Perform basic validation and return + return input.toLowerCase(); + } + + /** + * Print each time table + */ + private static void printSingleSchedule(int index, List schedule) { + // Sort + Collections.sort(schedule, (c1, c2) -> { + if (c1.getDay() != c2.getDay()) { + return Integer.compare(c1.getDay(), c2.getDay()); + } + return Integer.compare(c1.getStartTime(), c2.getStartTime()); + }); + + int totalCredit = 0; + for (Course c : schedule) totalCredit += c.getCredit(); + + + System.out.println(PURPLE + "\n ────────────────────────────────"); + System.out.println(String.format(" │ Recommended Timetable No.%02d │", index)); + System.out.println(" ────────────────────────────────" + RESET); + + if (schedule.isEmpty()) { + System.out.println(" " + YELLOW + "(Empty Schedule)" + RESET); + } else { + for (Course course : schedule) { + String dayStr = getDayString(course.getDay()); + String timeStr = formatTime(course.getStartTime()); + + System.out.println(" " + GREEN + String.format("[%s %s]", dayStr, timeStr) + RESET + + " " + course.getName() + " (" + course.getCredit() + " Credit)"); + } + } + System.out.println(" " + BLACK + "Total: " + totalCredit + " Credits" + RESET); + } + + /** + * Print choosing menu('next' or 'edit') + */ + private static void printNavigationMenu(boolean hasNext) { + System.out.println(CYAN + "\n-------------------------------------------------------------" + RESET); + + if (hasNext) { + System.out.println(" ( > ω < ) Select: [" + BLUE + "next" + RESET + "] or [" + RED + "edit" + RESET + "] "); + System.out.println(" Type '" + BLUE + "next" + RESET + "' to see more timetables."); + } else { + System.out.println(" ( > ω < ) Select: [" + RED + "edit" + RESET + "] "); + System.out.println(" " + YELLOW + "(End of List)" + RESET + " No more timetables."); + } + + System.out.println(" Type '" + RED + "edit" + RESET + "' to modify your courses."); + System.out.println(CYAN + "-------------------------------------------------------------" + RESET); + } + + // --- Utility Methods (Day/Time Conversion) --- + private static String getDayString(int day) { + switch (day) { + case 0: return "Mon"; case 1: return "Tue"; case 2: return "Wed"; + case 3: return "Thu"; case 4: return "Fri"; default: return "???"; + } + } + + private static String formatTime(int minutes) { + return String.format("%02d:%02d", minutes / 60, minutes % 60); + } +} \ No newline at end of file diff --git a/src/main/java/com/unitime/feature/Course.java b/src/main/java/com/unitime/feature/Course.java index f38153e..eb8a776 100644 --- a/src/main/java/com/unitime/feature/Course.java +++ b/src/main/java/com/unitime/feature/Course.java @@ -34,4 +34,4 @@ public String toString() { return String.format("%s | %d (credits) | %s ", name, credit, timeRaw); } -} +} \ No newline at end of file From eaae5efbbb113cf3bd59799f8a75a505d7df47cb Mon Sep 17 00:00:00 2001 From: Hyewon Date: Thu, 11 Dec 2025 23:50:51 +0900 Subject: [PATCH 2/2] Edit for exactly input --- src/main/java/com/unitime/App.java | 21 ++++++------------- src/main/java/com/unitime/UI/ResultView.java | 16 ++++++++++---- .../java/com/unitime/UI/ResultViewTest.java | 0 3 files changed, 18 insertions(+), 19 deletions(-) create mode 100644 src/test/java/com/unitime/UI/ResultViewTest.java diff --git a/src/main/java/com/unitime/App.java b/src/main/java/com/unitime/App.java index 56b1e31..a872934 100644 --- a/src/main/java/com/unitime/App.java +++ b/src/main/java/com/unitime/App.java @@ -3,31 +3,25 @@ import java.util.List; import java.util.Scanner; -// 지금까지 만든 파일들(패키지) 가져오기 + import com.unitime.UI.ResultView; import com.unitime.feature.InputHandler; import com.unitime.feature.Course; -import com.unitime.algorthm.Scheduler; // 패키지명 오타(algorthm) 주의! 수정했다면 algorithm으로 변경하세요. +import com.unitime.algorthm.Scheduler; public class App { public static void main( String[] args ) { - // 1. 프로그램 전체에서 쓸 스캐너 생성 + Scanner sc = new Scanner(System.in); - // 2. 인트로 화면 보여주기 (IntroScreen 코드가 있다면 주석 해제) - // IntroScreen.show(); - System.out.println("\n=== Welcome to UniTime-Solver! ==="); // 임시 인트로 + System.out.println("\n=== Welcome to UniTime-Solver! ==="); System.out.println("Press [ENTER] to start..."); sc.nextLine(); - // 3. 메인 무한 루프 (edit을 누르면 다시 여기로 돌아옴) while(true) { - // --- [STEP 1] 사용자 입력 받기 --- - // InputHandler가 생성되면서 사용자에게 과목 입력을 받음 InputHandler inputHandler = new InputHandler(); - // --- [STEP 2] 시간표 짜기 (알고리즘 가동) --- System.out.println("\n[Algorithm] Generating optimal timetables..."); Scheduler scheduler = new Scheduler(); List> results = scheduler.schedule( @@ -36,24 +30,21 @@ public static void main( String[] args ) { inputHandler.getMaxCredit() ); - // --- [STEP 3] 결과 보여주기 (View Loop) --- int currentIndex = 0; boolean viewingResults = true; while (viewingResults) { - // ResultView를 불러서 화면을 보여주고, 사용자의 선택("next" or "edit")을 받아옴 + String command = ResultView.printBatchAndGetInput(results, currentIndex, sc); if (command.equals("next")) { - // 다음 페이지로 이동 로직 + if (currentIndex + 5 < results.size()) { currentIndex += 5; } else { - // 더 이상 없는데 next 누른 경우 (ResultView에서 이미 메시지 띄웠으므로 패스) } } else if (command.equals("edit")) { - // 입력 화면으로 돌아가기 위해 내부 루프 탈출 -> 외부 while문의 처음으로 이동 viewingResults = false; } } diff --git a/src/main/java/com/unitime/UI/ResultView.java b/src/main/java/com/unitime/UI/ResultView.java index b30ca77..0f3472a 100644 --- a/src/main/java/com/unitime/UI/ResultView.java +++ b/src/main/java/com/unitime/UI/ResultView.java @@ -57,12 +57,21 @@ public static String printBatchAndGetInput(List> allSchedules, int printNavigationMenu(hasNext); // 5. Get user input and return + while (true) { System.out.print("Your choice > "); - String input = scanner.nextLine().trim(); + String input = scanner.nextLine().trim().toLowerCase(); - // Perform basic validation and return - return input.toLowerCase(); + //Edit: return only 'next' or 'edit' + if (input.equals("next") || input.equals("edit")) { + return input; + } + + //Enter wrong message -> input again (loop) + System.out.println(RED + "Invalid command! Please type 'next' or 'edit' exactly." + RESET); + + } +} /** * Print each time table @@ -78,7 +87,6 @@ private static void printSingleSchedule(int index, List schedule) { int totalCredit = 0; for (Course c : schedule) totalCredit += c.getCredit(); - System.out.println(PURPLE + "\n ────────────────────────────────"); System.out.println(String.format(" │ Recommended Timetable No.%02d │", index)); diff --git a/src/test/java/com/unitime/UI/ResultViewTest.java b/src/test/java/com/unitime/UI/ResultViewTest.java new file mode 100644 index 0000000..e69de29