From eab260c08bf754a78d673152293f4cc258599994 Mon Sep 17 00:00:00 2001 From: sajeev1003 <131582781+sajeev1003@users.noreply.github.com> Date: Wed, 1 Jan 2025 09:35:06 +0800 Subject: [PATCH] Add files via upload --- src/todolistapp/DatabaseUtil.java | 29 + src/todolistapp/HuggingFaceClient.java | 64 +++ src/todolistapp/Task.java | 110 ++++ src/todolistapp/TaskDAO.java | 44 ++ src/todolistapp/TaskManager.java | 734 +++++++++++++++++++++++++ src/todolistapp/ToDoApp.java | 99 ++++ src/todolistapp/VectorSearch.java | 80 +++ 7 files changed, 1160 insertions(+) create mode 100644 src/todolistapp/DatabaseUtil.java create mode 100644 src/todolistapp/HuggingFaceClient.java create mode 100644 src/todolistapp/Task.java create mode 100644 src/todolistapp/TaskDAO.java create mode 100644 src/todolistapp/TaskManager.java create mode 100644 src/todolistapp/ToDoApp.java create mode 100644 src/todolistapp/VectorSearch.java diff --git a/src/todolistapp/DatabaseUtil.java b/src/todolistapp/DatabaseUtil.java new file mode 100644 index 0000000..e7d0a6a --- /dev/null +++ b/src/todolistapp/DatabaseUtil.java @@ -0,0 +1,29 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + +/** + * + * @author Sajeev + */ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + + +public class DatabaseUtil{ + private static final String DB_URL = "jdbc:sqlite:C:\\Users\\Sajeev\\Downloads\\mydatabase\\vector_search.db"; + + public static Connection connect() { + Connection conn = null; + try { + conn = DriverManager.getConnection(DB_URL); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return conn; + } +} + diff --git a/src/todolistapp/HuggingFaceClient.java b/src/todolistapp/HuggingFaceClient.java new file mode 100644 index 0000000..92b7e91 --- /dev/null +++ b/src/todolistapp/HuggingFaceClient.java @@ -0,0 +1,64 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + +/** + * + * @author Sajeev + */ +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Scanner; + +public class HuggingFaceClient { + + private static final String API_URL = "https://api-inference.huggingface.co/models/sentence-transformers/all-MiniLM-L6-v2"; + private static final String API_KEY = "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"; + + + public static String generateEmbedding(String sourceSentence, String[] sentences) { + try { + URL url = new URL(API_URL); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Authorization", "Bearer " + API_KEY); + conn.setRequestProperty("Content-Type", "application/json"); + conn.setDoOutput(true); + + // Prepare JSON payload + StringBuilder sentencesArrayJson = new StringBuilder("["); + for (int i = 0; i < sentences.length; i++) { + sentencesArrayJson.append("\"").append(sentences[i]).append("\""); + if (i < sentences.length - 1) { + sentencesArrayJson.append(","); + } + } + sentencesArrayJson.append("]"); + + String payload = String.format("{\"inputs\": {\"source_sentence\": \"%s\", \"sentences\": %s}}", + sourceSentence, sentencesArrayJson.toString()); + + // Write payload + try (OutputStream os = conn.getOutputStream()) { + os.write(payload.getBytes()); + os.flush(); + } + + // Read response + Scanner scanner = new Scanner(conn.getInputStream()); + StringBuilder response = new StringBuilder(); + while (scanner.hasNextLine()) { + response.append(scanner.nextLine()); + } + scanner.close(); + + return response.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/src/todolistapp/Task.java b/src/todolistapp/Task.java new file mode 100644 index 0000000..5e19175 --- /dev/null +++ b/src/todolistapp/Task.java @@ -0,0 +1,110 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + +/** + * + * @author Sajeev + */ +import java.time.LocalDate; + +public class Task { + private String title; + private String description; + private LocalDate dueDate; + private boolean isComplete; + private String category; + private String priority; + private Task dependsOn; + private boolean isRecurring; + private String recurringInterval; + + // Constructor + public Task(String title, String description, LocalDate dueDate, String category, String priority, boolean isRecurring, String recurringInterval) { + this.title = title; + this.description = description; + this.dueDate = dueDate; + this.isComplete = false; + this.category = category; + this.priority = priority; + this.dependsOn = null; + this.isRecurring = isRecurring; + this.recurringInterval = recurringInterval; + } + + // Getters + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public LocalDate getDueDate() { + return dueDate; + } + + public boolean isComplete() { + return isComplete; + } + + public String getCategory() { + return category; + } + + public String getPriority() { + return priority; + } + + public Task getDependsOn() { + return dependsOn; + } + + public boolean isRecurring() { + return isRecurring; + } + + public String getRecurringInterval() { + return recurringInterval; + } + + // Setters + public void setTitle(String title) { + this.title = title; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setDueDate(LocalDate dueDate) { + this.dueDate = dueDate; + } + + public void setComplete(boolean complete) { + isComplete = complete; + } + + public void setCategory(String category) { + this.category = category; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + public void setDependsOn(Task dependsOn) { + this.dependsOn = dependsOn; + } + + public void setRecurring(boolean recurring) { + isRecurring = recurring; + } + + public void setRecurringInterval(String recurringInterval) { + this.recurringInterval = recurringInterval; + } +} diff --git a/src/todolistapp/TaskDAO.java b/src/todolistapp/TaskDAO.java new file mode 100644 index 0000000..107a0e2 --- /dev/null +++ b/src/todolistapp/TaskDAO.java @@ -0,0 +1,44 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + + + +/** + * + * @author Sajeev + */ + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class TaskDAO { + + public void insertTask(String title, String description, String dueDate, String category, String priority, String completionStatus) { + String sql = "INSERT INTO vector_tasks (title, description, due_date, category, priority, completion_status) VALUES (?, ?, ?, ?, ?, ?)"; + + try (Connection conn = DatabaseUtil.connect(); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + + pstmt.setString(1, title); + pstmt.setString(2, description); + pstmt.setString(3, dueDate); + pstmt.setString(4, category); + pstmt.setString(5, priority); + pstmt.setString(6, completionStatus); + + pstmt.executeUpdate(); + System.out.println("Task added successfully to the database!"); + + } catch (SQLException e) { + System.out.println("Error adding task to database: " + e.getMessage()); + } + } +} + + + + diff --git a/src/todolistapp/TaskManager.java b/src/todolistapp/TaskManager.java new file mode 100644 index 0000000..2f6fa8c --- /dev/null +++ b/src/todolistapp/TaskManager.java @@ -0,0 +1,734 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + +/** + * + * @author Sajeev + */ +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +public class TaskManager { + private List tasks; + private int taskCounter; + + public TaskManager() { + tasks = new ArrayList<>(); + taskCounter = 0; + } + + public void addTask(Scanner scanner) { + System.out.println("\u001B[31m=== Add a New Task ===\u001B[0m"); + + // Title validation with minimum length + String title; + while(true){ + System.out.print("Enter task title: "); + title = scanner.nextLine().trim(); + if(title.isEmpty()){ + System.out.println("\u001b[31mERROR:\u001b[0m Title cannot be empty. Please enter a title."); + System.out.println(); + }else if (title.length() < 3){ // Minimum 3 characters + System.out.println("\u001b[31mERROR:\u001b[0m Title must be at least 3 characters long."); + System.out.println(); + }else{ + break; + } + } + + // Description validation with minimum length + String description; + while(true){ + System.out.print("Enter task description: "); + description = scanner.nextLine().trim(); + if(description.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Description cannot be empty. Please enter a description."); + System.out.println(); + }else if(description.length() < 5){ // Minimum 5 characters + System.out.println("\u001b[31mERROR:\u001b[0m Description must be at least 5 characters long."); + System.out.println(); + }else{ + break; + } + } + + // Error Handling (Input Validation) + LocalDate dueDate; + while(true){ + try{ + System.out.print("Enter due date (YYYY-MM-DD): "); + String dateInput = scanner.nextLine().trim(); + + // Check for empty input + if(dateInput.isEmpty()){ + System.out.println("\u001b[31mERROR:\u001b[0m Date cannot be empty. Please enter a date."); + System.out.println(); + continue; // Skip rest of loop and start over + } + + // Replace "/" with "-" if user uses slashes + dateInput = dateInput.replace("/", "-"); + + // Parse the date + dueDate = LocalDate.parse(dateInput); + + // Check if date is in the past + if(dueDate.isBefore(LocalDate.now())){ + System.out.println("\u001b[31mERROR:\u001b[0m Due date cannot be in the past!"); + System.out.println(); + continue; // Skip rest of loop and start over + } + + break; // Valid date, exit loop + + }catch(Exception e){ + System.out.println("\u001b[31mERROR:\u001b[0m Invalid date format! Please use YYYY-MM-DD."); + System.out.println(); + } + } + // parse() request user to enter valid date type, + // It automatically throws a "DateTimeParseException" if the format is wrong + // Use error handling to + //-Catch exception + //-Print user friendly's error messege + //-Allowing User to try again + + // Error Handling (Input Validation) + String category; + while(true){ + System.out.print("Enter task category (Homework, Personal, Work): "); + category = scanner.nextLine(); + if(category.equalsIgnoreCase("Homework") || + category.equalsIgnoreCase("Personal") || + category.equalsIgnoreCase("Work")){ + category = capitalize(category); // Normalize to "Homework", "Personal", "Work" + break; + } + System.out.println("\u001b[31mERROR:\u001b[0m Invalid Category! Please choose Homework, Personal or Work."); + System.out.println(); + } + + String priority; + while(true){ + System.out.print("Enter task priority (High, Medium, Low): "); + priority = scanner.nextLine(); + if(priority.equalsIgnoreCase("High") || + priority.equalsIgnoreCase("Medium") || + priority.equalsIgnoreCase("Low")){ + priority = capitalize(priority); // Normalize to "High", "Medium", "Low" + break; + } + System.out.println("\u001b[31mError:\u001b[0m Invalid Priority! Please choose High, Medium or Low."); + System.out.println(); + } + + // Recurring task validation + String recurringInterval = null; + while (true) { + System.out.print("Is this task recurring? (yes/no): "); + String recurringInput = scanner.nextLine().trim().toLowerCase(); + + if (recurringInput.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Please enter 'yes' or 'no'."); + System.out.println(); + continue; + } + + if (!recurringInput.equals("yes") && !recurringInput.equals("no")) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid input. Please enter 'yes' or 'no'."); + System.out.println(); + continue; + } + + boolean isRecurring = recurringInput.equals("yes"); + + if (isRecurring) { + while (true) { + System.out.print("Enter recurring interval (Daily, Weekly, Monthly): "); + recurringInterval = scanner.nextLine().trim(); + + if (recurringInterval.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Interval cannot be empty."); + System.out.println(); + continue; + } + + // Normalize input to lowercase for comparison + String normalizedInterval = recurringInterval.toLowerCase(); + if (!normalizedInterval.equals("daily") && + !normalizedInterval.equals("weekly") && + !normalizedInterval.equals("monthly")) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid interval. Please enter Daily, Weekly, or Monthly."); + System.out.println(); + continue; + } + + // Capitalize first letter for consistency + recurringInterval = recurringInterval.substring(0, 1).toUpperCase() + + recurringInterval.substring(1).toLowerCase(); + break; + } + } + + Task newTask = new Task(title, description, dueDate, category, priority, isRecurring, recurringInterval); + tasks.add(newTask); + taskCounter++; + + // Save the task to the database + TaskDAO taskDAO = new TaskDAO(); + taskDAO.insertTask(title, description, dueDate.toString(), category, priority, "Incomplete"); + + //NOTIFY USER + System.out.println("\n\u001b[32mTask [" + title + "] added successfully!\u001b[0m"); + break; + } + } + + public void markTaskComplete(Scanner scanner) { + System.out.println("\u001B[31m=== Mark Task as Complete ===\u001B[0m"); + displayTasks(); + + while (true) { // Add while loop to allow retries + try { + System.out.print("Enter the task number you want to mark as complete: "); + String input = scanner.nextLine().trim(); + + // Check for empty input + if (input.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Task number cannot be empty."); + System.out.println(); + continue; // Go back to start of loop + } + + // Convert to integer after checking for empty + int taskNum = Integer.parseInt(input) - 1; + + // Check for out of range + if (taskNum < 0 || taskNum >= tasks.size()) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid task number. Please enter a valid number."); + System.out.println(); + continue; // Go back to start of loop + } + + Task task = tasks.get(taskNum); + + // Check dependencies + if (task.getDependsOn() != null && !task.getDependsOn().isComplete()) { + System.out.println("\u001b[31mWARNING:\u001b[0m Task \"" + task.getTitle() + + "\" cannot be marked as complete because it depends on [" + + task.getDependsOn().getTitle() + "]. Please complete [" + + task.getDependsOn().getTitle() + "] first."); + System.out.println(); + return; // Return here as this is a logical constraint, not an input error + } + + task.setComplete(true); + System.out.println("\n\u001b[32mTask [" + task.getTitle() + "] marked as completed!\u001b[0m"); + + if (task.isRecurring()) { + LocalDate newDueDate = calculateNewDueDate(task.getDueDate(), task.getRecurringInterval()); + Task recurringTask = new Task(task.getTitle(), task.getDescription(), newDueDate, + task.getCategory(), task.getPriority(), true, task.getRecurringInterval()); + tasks.add(recurringTask); + System.out.println("\nRecurring task \"" + recurringTask.getTitle() + + "\" added with new due date: " + newDueDate); + } + + break; // Exit loop on success + + } catch (NumberFormatException e) { + System.out.println("\u001b[31mERROR:\u001b[0m Please enter a valid number."); + System.out.println(); + continue; // Go back to start of loop + } + } + } + + public void deleteTask(Scanner scanner) { + System.out.println("\u001B[31m=== Delete a Task ===\u001B[0m"); + displayTasks(); + + while (true) { // Add while loop for retries + try { + System.out.print("Enter the task number you want to delete: "); + String input = scanner.nextLine().trim(); + + // Check for empty input + if (input.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Task number cannot be empty."); + System.out.println(); + continue; + } + + // Convert to integer after checking for empty + int taskNum = Integer.parseInt(input) - 1; + + // Check for out of range + if (taskNum < 0 || taskNum >= tasks.size()) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid task number. Please enter a valid number."); + System.out.println(); + continue; + } + + // Original delete logic + Task removedTask = tasks.remove(taskNum); + taskCounter--; + System.out.println("\u001b[32mTask [" + removedTask.getTitle() + "] deleted successfully!\u001b[0m"); + break; // Exit loop after successful deletion + + } catch (NumberFormatException e) { + System.out.println("\u001b[31mERROR:\u001b[0m Please enter a valid number."); + System.out.println(); + continue; + } + } + } + + public void sortTasks(Scanner scanner) { + System.out.println("\u001B[31m=== Sort Tasks ===\u001B[0m"); + System.out.println("Sort by:"); + System.out.println("1. Due Date (Ascending)"); + System.out.println("2. Due Date (Descending)"); + System.out.println("3. Priority (High to Low)"); + System.out.println("4. Priority (Low to High)"); + System.out.print("\n> "); + + int choice = Integer.parseInt(scanner.nextLine()); + String choiceName = ""; + + switch (choice) { + case 1: + tasks.sort(Comparator.comparing(Task::getDueDate)); + break; + case 2: + tasks.sort(Comparator.comparing(Task::getDueDate).reversed()); + break; + case 3: + tasks.sort((t1, t2) -> comparePriority(t2.getPriority(), t1.getPriority())); + break; + case 4: + tasks.sort((t1, t2) -> comparePriority(t1.getPriority(), t2.getPriority())); + break; + } + + if(choice == 1){ + choiceName = "Due Date (Ascending)"; + }else if(choice ==2){ + choiceName = "Due Date (Descending)"; + }else if(choice == 3){ + choiceName = "Priority (High to Low)"; + }else if(choice == 4){ + choiceName = "Priority (Low to High)"; + } + + System.out.printf("\n\u001b[32mTasks sorted by %s!\u001b[0m", choiceName); + System.out.println(); + } + + private int comparePriority(String p1, String p2) { + Map priorityMap = Map.of( + "High", 3, + "Medium", 2, + "Low", 1 + ); + return priorityMap.get(p1) - priorityMap.get(p2); + } + + // Helper method to capitalize input + private String capitalize(String input) { + if (input == null || input.isEmpty()) { + return input; + } + return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase(); + } + + public void searchTasks(Scanner scanner) { + System.out.println("\u001B[31m=== Search Tasks ===\u001B[0m"); + System.out.print("Enter a keyword to search by title or description: "); + String keyword = scanner.nextLine().toLowerCase(); + + System.out.println("\n\u001b[31m=== Search Results ===\u001b[0m"); + boolean found = false; + for (int i = 0; i < tasks.size(); i++) { + Task task = tasks.get(i); + if (task.getTitle().toLowerCase().contains(keyword) || + task.getDescription().toLowerCase().contains(keyword)) { + printTask(task, i + 1); + found = true; + } + } + if (!found) { + System.out.println("\u001b[31mWARNING:\u001b[0m No tasks found matching your search."); + } + } + + + public void vectorSearchTasks(Scanner scanner) { + System.out.println("\u001B[31m=== Search Tasks ===\u001B[0m"); + System.out.print("Enter a keyword or phrase to search tasks: "); + String query = scanner.nextLine(); + + VectorSearch vectorSearch = new VectorSearch(); + List results = vectorSearch.searchTasks(query); + + System.out.println("\n\u001b[31m=== Vector Search Results ===\u001b[0m"); + if (results.isEmpty()) { + System.out.println("\u001b[31mWARNING:\u001b[0m No tasks found matching your search."); + } else { + for (String result : results) { + System.out.println(result); + } + } + } + + public void setTaskDependency(Scanner scanner) { + System.out.println("\u001B[31m=== Set Task Dependency ===\u001B[0m"); + displayTasks(); + + // Check if there are enough tasks + if (tasks.size() < 2) { + System.out.println("\u001b[31mERROR:\u001b[0m You need at least 2 tasks to set up dependencies."); + return; + } + + while (true) { // Add while loop for retries + try { + System.out.print("Enter task number that depends on another task: "); + String input = scanner.nextLine().trim(); + + // Check for empty input + if (input.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Task number cannot be empty."); + System.out.println(); + continue; + } + + // Convert to integer after checking for empty + int dependentTaskNum = Integer.parseInt(input) - 1; + + // Validate first task number + if (dependentTaskNum < 0 || dependentTaskNum >= tasks.size()) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid task number. Please enter a number between 1 and " + tasks.size() + "."); + System.out.println(); + continue; + } + + System.out.print("Enter the task number it depends on: "); + input = scanner.nextLine().trim(); + + // Check for empty input for second task + if (input.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Task number cannot be empty."); + System.out.println(); + continue; + } + + // Convert to integer after checking for empty + int precedingTaskNum = Integer.parseInt(input) - 1; + + // Validate second task number + if (precedingTaskNum < 0 || precedingTaskNum >= tasks.size()) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid task number. Please enter a number between 1 and " + tasks.size() + "."); + System.out.println(); + continue; + } + + // Check if trying to make a task depend on itself + if (dependentTaskNum == precedingTaskNum) { + System.out.println("\u001b[31mERROR:\u001b[0m A task cannot depend on itself."); + System.out.println(); + continue; + } + + Task dependentTask = tasks.get(dependentTaskNum); + Task precedingTask = tasks.get(precedingTaskNum); + + // Check for circular dependency + if (wouldCreateCycle(precedingTask, dependentTask)) { + System.out.println("\u001b[31mERROR:\u001b[0m This would create a circular dependency!"); + System.out.println(); + continue; + } + + dependentTask.setDependsOn(precedingTask); + System.out.println("\n\u001b[32mTask [" + dependentTask.getTitle() + + "] now depends on [" + precedingTask.getTitle() + "].\u001b[0m"); + break; // Exit loop after successful dependency set + + } catch (NumberFormatException e) { + System.out.println("\u001b[31mERROR:\u001b[0m Please enter a valid number."); + System.out.println(); + continue; + } + } + } + + private boolean wouldCreateCycle(Task start, Task newDependency) { + // Create an empty HashSet to track visited tasks + Set visited = new HashSet<>(); + + // Start with the first task in the chain + Task current = start; + + // Keep going until we reach a task with no dependencies (null) + while (current != null) { + // Try to add current task to visited set + // visited.add() returns false if task is already in set + if (!visited.add(current)) { + return true; // Found a cycle - task was already visited + } + if (current == newDependency) { + return true; // Found a cycle - would create circular dependency + } + current = current.getDependsOn(); + } + return false; // No cycle found + } + + public void editTask(Scanner scanner) { + System.out.println("\u001B[31m=== Edit Task ===\u001B[0m"); + displayTasks(); + + while (true) { // Add while loop for retries + try { + System.out.print("Enter the task number you want to edit: "); + String input = scanner.nextLine().trim(); + + // Check for empty input + if (input.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Task number cannot be empty."); + System.out.println(); + continue; + } + + // Convert to integer after checking for empty + int taskNum = Integer.parseInt(input) - 1; + + // Check for out of range + if (taskNum < 0 || taskNum >= tasks.size()) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid task number. Please enter a valid number."); + System.out.println(); + continue; + } + + // Original edit logic + Task task = tasks.get(taskNum); + System.out.println("What would you like to edit?"); + System.out.println("1. Title"); + System.out.println("2. Description"); + System.out.println("3. Due Date"); + System.out.println("4. Category"); + System.out.println("5. Priority"); + System.out.println("6. Set Task Dependency"); + System.out.println("7. Cancel"); + System.out.print("\n> "); + + int choice = Integer.parseInt(scanner.nextLine()); + switch (choice) { + case 1: + System.out.print("Enter new title: "); + task.setTitle(scanner.nextLine()); + break; + case 2: + System.out.print("Enter new description: "); + task.setDescription(scanner.nextLine()); + break; + case 3: + System.out.print("Enter new due date (YYYY-MM-DD): "); + task.setDueDate(LocalDate.parse(scanner.nextLine())); + break; + case 4: + System.out.print("Enter new category: "); + task.setCategory(scanner.nextLine()); + break; + case 5: + System.out.print("Enter new priority (Low, Medium, High): "); + task.setPriority(scanner.nextLine()); + break; + case 6: + setTaskDependency(scanner); + break; + case 7: + return; + } + System.out.println("\n\u001b[32mTask updated successfully!\u001b[0m"); + break; // Exit loop after successful edit + + } catch (NumberFormatException e) { + System.out.println("\u001b[31mERROR:\u001b[0m Please enter a valid number."); + System.out.println(); + continue; + } + } + } + + public void viewAllTasks() { + System.out.println("\u001B[31m=== View All Tasks ===\u001B[0m"); + if (tasks.isEmpty()) { + System.out.println("\n\u001b[31mWARNING:\u001b[0m No tasks found."); + return; + } + + for (int i = 0; i < tasks.size(); i++) { + printTask(tasks.get(i), i + 1); + } + + System.out.println("\nThe total number of tasks created is " + taskCounter + "."); + } + + public void viewTaskDetails(Scanner scanner) { + System.out.println("\u001B[31m=== View Task Details ===\u001B[0m"); + displayTasks(); + + if (tasks.isEmpty()) { + return; + } + + while (true) { // Add while loop for retries + try { + System.out.print("Enter task number to view details: "); + String input = scanner.nextLine().trim(); + + // Check for empty input + if (input.isEmpty()) { + System.out.println("\u001b[31mERROR:\u001b[0m Task number cannot be empty."); + System.out.println(); + continue; + } + + // Convert to integer after checking for empty + int taskNum = Integer.parseInt(input) - 1; + + // Check for out of range + if (taskNum < 0 || taskNum >= tasks.size()) { + System.out.println("\u001b[31mERROR:\u001b[0m Invalid task number. Please enter a valid number."); + System.out.println(); + continue; + } + + // Original view details logic + Task task = tasks.get(taskNum); + System.out.println("\n\u001b[35mTask Details:\u001b[0m"); + System.out.println("Title: " + task.getTitle()); + System.out.println("Description: " + task.getDescription()); + System.out.println("Due Date: " + task.getDueDate()); + System.out.println("Category: " + task.getCategory()); + System.out.println("Priority: " + task.getPriority()); + System.out.println("Status: " + (task.isComplete() ? "Completed" : "Incomplete")); + if (task.getDependsOn() != null) { + System.out.println("Depends on: " + task.getDependsOn().getTitle()); + } + if (task.isRecurring()) { + System.out.println("Recurring: Yes (" + task.getRecurringInterval() + ")"); + } + break; // Exit loop after successful view + + } catch (NumberFormatException e) { + System.out.println("\u001b[31mERROR:\u001b[0m Please enter a valid number."); + System.out.println(); + continue; + } + } + } + + private void printTask(Task task, int taskNum) { + System.out.printf("%d. [%s] %s - Due: %s - Category: %s - Priority: %s%s%n", + taskNum, + task.isComplete() ? "Completed" : "Incomplete", + task.getTitle(), + task.getDueDate().format(DateTimeFormatter.ISO_LOCAL_DATE), + task.getCategory(), + task.getPriority(), + task.getDependsOn() != null ? " (Depends on: " + task.getDependsOn().getTitle() + ")" : "" + ); + } + + // To display the tasks only + private void displayTasks() { + if (tasks.isEmpty()) { + System.out.println("\u001b[31mWARNING:\u001b[0m No tasks found."); + return; + } + + for (int i = 0; i < tasks.size(); i++) { + printTask(tasks.get(i), i + 1); + } + System.out.println(); + } + + private LocalDate calculateNewDueDate(LocalDate currentDueDate, String interval) { + switch (interval.toLowerCase()) { + case "daily": + return currentDueDate.plusDays(1); + case "weekly": + return currentDueDate.plusWeeks(1); + case "monthly": + return currentDueDate.plusMonths(1); + default: + throw new IllegalArgumentException("\nInvalid recurring interval"); + } + } + public void displayAnalytics() { + try (Connection conn = DatabaseUtil.connect()) { + String totalTasksQuery = "SELECT COUNT(*) AS total FROM vector_tasks"; + String completedTasksQuery = "SELECT COUNT(*) AS completed FROM vector_tasks WHERE completion_status = 'Completed'"; + String pendingTasksQuery = "SELECT COUNT(*) AS pending FROM vector_tasks WHERE completion_status = 'Incomplete'"; + String categorySummaryQuery = "SELECT category, COUNT(*) AS count FROM vector_tasks GROUP BY category"; + + // Total tasks + PreparedStatement totalStmt = conn.prepareStatement(totalTasksQuery); + ResultSet totalRs = totalStmt.executeQuery(); + int totalTasks = totalRs.next() ? totalRs.getInt("total") : 0; + + // Completed tasks + PreparedStatement completedStmt = conn.prepareStatement(completedTasksQuery); + ResultSet completedRs = completedStmt.executeQuery(); + int completedTasks = completedRs.next() ? completedRs.getInt("completed") : 0; + + // Pending tasks + PreparedStatement pendingStmt = conn.prepareStatement(pendingTasksQuery); + ResultSet pendingRs = pendingStmt.executeQuery(); + int pendingTasks = pendingRs.next() ? pendingRs.getInt("pending") : 0; + + // Completion rate + double completionRate = totalTasks > 0 ? (double) completedTasks / totalTasks * 100 : 0; + + // Task categories + PreparedStatement categoryStmt = conn.prepareStatement(categorySummaryQuery); + ResultSet categoryRs = categoryStmt.executeQuery(); + StringBuilder categorySummary = new StringBuilder(); + while (categoryRs.next()) { + String category = categoryRs.getString("category"); + int count = categoryRs.getInt("count"); + categorySummary.append(category).append(": ").append(count).append(", "); + } + if (categorySummary.length() > 0) { + categorySummary.setLength(categorySummary.length() - 2); // Remove trailing comma and space + } + + // Display the analytics dashboard + System.out.println("\u001B[31m=== Analytics Dashboard ===\u001B[0m"); + System.out.println("- Total Tasks: " + totalTasks); + System.out.println("- Completed: " + completedTasks); + System.out.println("- Pending: " + pendingTasks); + System.out.printf("- Completion Rate: %.2f%%\n", completionRate); + System.out.println("- Task Categories: " + categorySummary.toString()); + + } catch (Exception e) { + System.out.println("Error generating analytics: " + e.getMessage()); + e.printStackTrace(); + } +} + + + +} + + diff --git a/src/todolistapp/ToDoApp.java b/src/todolistapp/ToDoApp.java new file mode 100644 index 0000000..c5118f1 --- /dev/null +++ b/src/todolistapp/ToDoApp.java @@ -0,0 +1,99 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + +import java.util.Scanner; + +/** + * + * @author Sajeev + */ +// Main application class +public class ToDoApp { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + TaskManager taskManager = new TaskManager(); + boolean running = true; + + while (running) { + System.out.println("\n\u001B[33m[JAVA TODO LIST APP (OOP)]\u001B[0m"); + System.out.println(); + System.out.println("1. Add a task"); + System.out.println("2. View all tasks"); + System.out.println("3. Mark task as completed"); + System.out.println("4. Delete a task"); + System.out.println("5. Task Sorting"); + System.out.println("6. Search tasks"); + System.out.println("7. Search tasks using Vector Search"); + System.out.println("8. Set task dependency"); + System.out.println("9. Edit task"); + System.out.println("10. View Task Details"); + System.out.println("11. Display Analytics Dashboard"); + System.out.println("12. Exit"); + System.out.print("\nEnter your choice: "); + + try { + int choice = Integer.parseInt(scanner.nextLine()); + System.out.println(); + + switch (choice) { + case 1: + taskManager.addTask(scanner); + break; + case 2: + taskManager.viewAllTasks(); + break; + case 3: + taskManager.markTaskComplete(scanner); + break; + case 4: + taskManager.deleteTask(scanner); + break; + case 5: + taskManager.sortTasks(scanner); + break; + case 6: + taskManager.searchTasks(scanner); + break; + case 7: + taskManager.vectorSearchTasks(scanner); + break; + case 8: + taskManager.setTaskDependency(scanner); + break; + case 9: + taskManager.editTask(scanner); + break; + case 10: + taskManager.viewTaskDetails(scanner); + break; + case 11: + taskManager.displayAnalytics(); + break; + case 12: + running = false; + System.out.println("\u001b[32mThank you for using the TODO List App!\u001b[0m"); + break; + default: + System.out.println("\\u001b[31mError:\\u001b[0m Invalid choice. Please choose between 1-9."); + } + if (running) { + System.out.print("\nPress Enter to continue..."); + scanner.nextLine(); + } + + System.out.println(); + } catch (Exception e) { + System.out.println("\u001b[31mError:\u001b[0m " + e.getMessage() +". Please choose between 1-12."); + System.out.println(); + } // Can use NumberFormatException(non numeric input: abc) of IllegalArgumentException(outside valid range) + } + + scanner.close(); + } +} + + + diff --git a/src/todolistapp/VectorSearch.java b/src/todolistapp/VectorSearch.java new file mode 100644 index 0000000..574a1b7 --- /dev/null +++ b/src/todolistapp/VectorSearch.java @@ -0,0 +1,80 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package todolistapp; + +/** + * + * @author Sajeev + */ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class VectorSearch { + + public List searchTasks(String query) { + List results = new ArrayList<>(); + String sql = "SELECT title, description, due_date, category, priority, completion_status FROM vector_tasks"; + + try (Connection conn = DatabaseUtil.connect(); + PreparedStatement pstmt = conn.prepareStatement(sql); + ResultSet rs = pstmt.executeQuery()) { + + // Collect descriptions and full task details during the first iteration + List descriptions = new ArrayList<>(); + List> taskDetails = new ArrayList<>(); + + while (rs.next()) { + descriptions.add(rs.getString("description")); + Map task = new HashMap<>(); + + task.put("title", rs.getString("title")); + task.put("due_date", rs.getString("due_date")); + task.put("category", rs.getString("category")); + task.put("completion_status", rs.getString("completion_status")); + + taskDetails.add(task); + + } + + // Generate similarity scores + String[] descriptionArray = descriptions.toArray(new String[0]); + String response = HuggingFaceClient.generateEmbedding(query, descriptionArray); + + // Parse similarity scores and filter results + if (response != null && !response.isEmpty()) { + + String sanitizedResponse = response.replace("[", "").replace("]", ""); + + // Parse response (mock parsing; adjust based on actual API response) + String[] scores = sanitizedResponse.split(","); // Adjust parsing logic + for (int i = 0; i < descriptions.size(); i++) { + double similarity = Double.parseDouble(scores[i].trim()); // Trim to remove extra spaces + + if (similarity > 0.8) { + Map task = taskDetails.get(i); + String result = String.format( + "[%s] %s - Due: %s - Category: %s", + task.get("completion_status"), // Completion status at the beginning + task.get("title"), // Title + task.get("due_date"), // Due date + task.get("category") // Category + ); + results.add(result); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return results; + } +} + +