diff --git a/.gitignore b/.gitignore index 2873e189e1..d31121226b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,12 @@ bin/ /text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT +/data/ +/trigoGraphAnalyser.log.1 +/trigoGraphAnalyser.log.1.lck +/trigoGraphAnalyser.log.2 +/trigoGraphAnalyser.log.2.lck +/trigoGraphAnalyser.log.3 +/trigoGraphAnalyser.log.3.lck +/trigoGraphAnalyser.log.4 +/trigoGraphAnalyser.log.lck diff --git a/Help b/Help new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Notes b/Notes new file mode 100644 index 0000000000..e69de29bb2 diff --git a/README.md b/README.md index f82e2494b7..6dfb24d2f5 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,46 @@ -# Duke project template +# _BadMaths_ ➕➖✖️➗ -This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it. +BadMaths is an integrated study tool that performs Mathematical Operations and contains various features for note-taking. -## Setting up in Intellij +To help you get started, our team has put together this user guide to guide you on the steps to operate BadMaths for your study woes. + +## Setting up Prerequisites: JDK 11 (use the exact version), update Intellij to the most recent version. 1. **Ensure Intellij JDK 11 is defined as an SDK**, as described [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk) -- this step is not needed if you have used JDK 11 in a previous Intellij project. -1. **Import the project _as a Gradle project_**, as described [here](https://se-education.org/guides/tutorials/intellijImportGradleProject.html). -1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/duke/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below: - ``` - > Task :compileJava - > Task :processResources NO-SOURCE - > Task :classes - - > Task :Duke.main() - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - - What is your name? - ``` - Type some word and press enter to let the execution proceed to the end. - -## Build automation using Gradle - -* This project uses Gradle for build automation and dependency management. It includes a basic build script as well (i.e. the `build.gradle` file). -* If you are new to Gradle, refer to the [Gradle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/gradle.html). - -## Testing - -### I/O redirection tests - -* To run _I/O redirection_ tests (aka _Text UI tests_), navigate to the `text-ui-test` and run the `runtest(.bat/.sh)` script. - -### JUnit tests - -* A skeleton JUnit test (`src/test/java/seedu/duke/DukeTest.java`) is provided with this project template. -* If you are new to JUnit, refer to the [JUnit Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/junit.html). - -## Checkstyle - -* A sample CheckStyle rule configuration is provided in this project. -* If you are new to Checkstyle, refer to the [Checkstyle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/checkstyle.html). - -## CI using GitHub Actions - -The project uses [GitHub actions](https://github.com/features/actions) for CI. When you push a commit to this repo or PR against it, GitHub actions will run automatically to build and verify the code as updated by the commit/PR. - -## Documentation - -`/docs` folder contains a skeleton version of the project documentation. - -Steps for publishing documentation to the public: -1. If you are using this project template for an individual project, go your fork on GitHub.
- If you are using this project template for a team project, go to the team fork on GitHub. -1. Click on the `settings` tab. -1. Scroll down to the `GitHub Pages` section. -1. Set the `source` as `master branch /docs folder`. -1. Optionally, use the `choose a theme` button to choose a theme for your documentation. +2. Download the latest JAR release [here](https://github.com/AY2223S2-CS2113-F10-2/tp/releases). +3. Copy the JAR file into an empty folder. +4. Open up a command window in that folder and run the following command: +``` +java -jar BadMaths.jar +``` +If the set-up is correct, you should see the following: +``` +____ _ __ __ _ _ +| _ \ | | | \/ | | | | | +| |_) | __ _ __| | | \ / | __ _| |_| |__ ___ +| _ < / _` |/ _` | | |\/| |/ _` | __| '_ \/ __| +| |_) | (_| | (_| | | | | | (_| | |_| | | \__ \ +|____/ \__,_|\__,_| |_| |_|\__,_|\__|_| |_|___/ +You can type 'Help' to learn what I can do for you :) +``` + +## Features (v2.1) +#### Monday, April 10, 2023 + +1. **Basic mathematical operations** + - Analyse trigonometry equations / sinusoidal signals + - Solve quadratic equations + - Solve matrix calculations +2. **Notes taking** + - Store, delete and list notes + - Mark or unmark the notes as done + - Rank and display notes based on priority + - Find notes based on keywords + + +Useful links: +* [User Guide](UserGuide.md) +* [Developer Guide](DeveloperGuide.md) +* [About Us](AboutUs.md) diff --git a/Store b/Store new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build.gradle b/build.gradle index d5e548e85f..3d7e38cd6d 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,8 @@ repositories { dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' + testImplementation 'junit:junit:4.13.1' + testImplementation 'org.testng:testng:7.1.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' } @@ -25,15 +27,18 @@ test { showCauses true showStackTraces true showStandardStreams = false + options { + jvmArgs '-Djava.awt.headless=true' + } } } application { - mainClass = "seedu.duke.Duke" + mainClass = "seedu.badmaths.BadMaths" } shadowJar { - archiveBaseName = "duke" + archiveBaseName = "badmaths" archiveClassifier = null } @@ -44,3 +49,18 @@ checkstyle { run{ standardInput = System.in } + +run { + enableAssertions = true +} + +jar { + manifest { + attributes 'Main-Class': 'seedu.badmaths.BadMaths' + } + duplicatesStrategy = 'exclude' // or 'fail', 'warn', 'preserve' + from sourceSets.main.output + from(sourceSets.main.resources) { + include '**/*.txt' + } +} diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..84fd7917ce 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,10 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +| Display | Name | Github Profile | Portfolio | +|-------------------------------------------------------------------------------------------|:------------------:|:------------------------------------------:|:-------------------------------------------------------------------------------:| +| img_1.png | Wilson Lee Jun Wei | [Github](https://github.com/WilsonLee2000) | [Portfolio](https://ay2223s2-cs2113-f10-2.github.io/tp/team/wilsonlee2000.html) | +| img_1.png | Khoo You Run | [Github](https://github.com/khooyourun) | [Portfolio](https://ay2223s2-cs2113-f10-2.github.io/tp/team/khooyourun.html) | +| img_1.png | Hui Yu Cong | [Github](https://github.com/YC-Michael) | [Portfolio](https://ay2223s2-cs2113-f10-2.github.io/tp/team/yc-michael.html) | +| img_1.png | Zeng Ziqiu | [Github](https://github.com/ZiqiuZeng) | [Portfolio](https://ay2223s2-cs2113-f10-2.github.io/tp/team/ziqiuzeng.html) | +| img_1.png | Seungjun Lee | [Github](https://github.com/0nandon) | [Portfolio](https://ay2223s2-cs2113-f10-2.github.io/tp/team/0nandon.html) | + diff --git a/docs/ArchitectureDiagram/Architecture_diagram.png b/docs/ArchitectureDiagram/Architecture_diagram.png new file mode 100644 index 0000000000..c86f2f32c7 Binary files /dev/null and b/docs/ArchitectureDiagram/Architecture_diagram.png differ diff --git a/docs/ClassDiagrams/BadMaths_class_diagram.png b/docs/ClassDiagrams/BadMaths_class_diagram.png new file mode 100644 index 0000000000..1ba352168c Binary files /dev/null and b/docs/ClassDiagrams/BadMaths_class_diagram.png differ diff --git a/docs/ClassDiagrams/MatrixClassDiagram.png b/docs/ClassDiagrams/MatrixClassDiagram.png new file mode 100644 index 0000000000..e83f62b7f3 Binary files /dev/null and b/docs/ClassDiagrams/MatrixClassDiagram.png differ diff --git a/docs/ClassDiagrams/Quadratic_class_diagram.png b/docs/ClassDiagrams/Quadratic_class_diagram.png new file mode 100644 index 0000000000..da5d67ebc3 Binary files /dev/null and b/docs/ClassDiagrams/Quadratic_class_diagram.png differ diff --git a/docs/ClassDiagrams/graph_class_diagram.png b/docs/ClassDiagrams/graph_class_diagram.png new file mode 100644 index 0000000000..b67da1b539 Binary files /dev/null and b/docs/ClassDiagrams/graph_class_diagram.png differ diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..f17a614bb7 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,38 +1,714 @@ # Developer Guide +This developer guide will help you to get started with our product, BadMaths! + +BadMaths is an integrated study tool that performs Mathematical Operations and contains +various features for note-taking. + +## Table of Contents + + +* [Developer Guide](#developer-guide) + * [Table of Contents](#table-of-contents) + * [Acknowledgements](#acknowledgements) + * [Design & implementation](#design--implementation) + * [Handling Of User Input](#handling-of-user-input) + * [Solving Quadratic Equations](#solving-quadratic-equations) + * [Notes](#notes) + * [Storage](#storage) + * [Store class:](#store-class) + * [List class:](#list-class) + * [Delete class:](#delete-class) + * [CommandHistory class:](#commandhistory-class) + * [Command class:](#command-class) + * [Ui class:](#ui-class) + * [NotePriority class:](#notepriority-class) + * [Help](#help) + * [Graph](#graph) + * [Matrix](#matrix) + * [Product Scope](#product-scope) + * [User Stories](#user-stories) + * [Non-Functional Requirements](#non-functional-requirements) + * [Glossary](#glossary) + * [Instructions for manual testing](#instructions-for-manual-testing) + ## Acknowledgements -{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +- The `Files.createTempFile` and `Files.delete` code snippets: [docs.oracle.com](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/PrintWriter.html). +- The information on redirecting `System.in` and `System.out`: [Unit Testing of System.out.println() with JUnit](https://www.baeldung.com/java-testing-system-out-println). +- The solution for JUnit testing with simulated user input [JUnit testing with simulated user input](https://stackoverflow.com/questions/6415728/junit-testing-with-simulated-user-input/6416142). +- The solution for adding resource files to a JAR file using Gradle: [Add resources and config files to your JAR using Gradle](https://stackoverflow.com/questions/24724383/add-resources-and-config-files-to-your-jar-using-gradle). +- The solution for exiting a Java program after a certain time: [How to make Java program exit after a couple of seconds](https://stackoverflow.com/questions/15747277/how-to-make-java-program-exit-after-a-couple-of-seconds). ## Design & implementation -{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +The Architecture Diagram below showcases the high level design of BadMaths: +
+Architecture Diagram +
-## Product scope -### Target user profile +![img.png](ArchitectureDiagram/Architecture_diagram.png) + +
+
+ +### Handling Of User Input + +
+Class Diagram for handling of User Input +
+ +![img_1.png](ClassDiagrams/BadMaths_class_diagram.png) + +
+
+ +The BadMaths class first reads the User's input and separates it into 2 parts, `command` and `toDo`. It does this by calling +the Parser class via `getCommand()` and `getToDo()`. BadMaths then checks whether `command` is valid using `commandChecker()`. +If it is not valid, the Ui class would be called upon to notify the User as such. If it is valid, `command` and `toDo` would be +passed into the Command class and the method `executeCommand()` would run the corresponding code. + +### Solving Quadratic Equations +The Quadratic equation solver allows user to find the value of `x` in a simple quadratic equation. +The function is started when `solveQuadratic()` is called in the Command class. + +Class Diagram: + +
+Class Diagram for Quadratic +
+ +![img.png](ClassDiagrams/Quadratic_class_diagram.png) + +
+
+ +Below is an example of how it would be called. +``` +Quadratic 2x^2 + 3x + 1 +``` +Step 1. Parser class would split the user input into 2 parts, command and toDo. Command would be `Quadratic`, +thus `executeCommand` in the Command class would trigger `quadraticSolver`. `toDo` would be `2x^2 + 3x + 1`. + +Step 2. The general formula of quadratic equations is `ax^2 + bx + c`, thus `findA`, `findB`, `findC` would be called from QuadraticParser +which extends from Quadratic. These methods would identify a, b and c from toDo. +- `findA` takes in `toDo` and uses substring function to isolate a from the rest of the equation. It would thus return a as +a `Double` data type. +- `findB` takes in `toDo` and calls `findSignOfB` and `findStringOfB` to identify the sign (+/-) and the number B as a `string` +This is done using substrings based on the index of the characters. `findB` then converts it into a `double` data type. +- `findC` takes in `toDo` and calls `findSignOfC` and `findStringOfC` to identify the sign (+/-) and the number C as a `string` +This is done using substrings based on the index of the characters, `findC` then converts it into a `double` data type. + +Step 3. To solve the quadratic equation, `quadraticFormula(a,b,c)` is called with a, b and c as parameters. +- The parameters are put into the equation `x = (-b±√(b²-4ac))/(2a)`. The output would be an ArrayList of Doubles that contains 2 values which +are the possible values of x. +- There is a possibility that the x values are imaginary, in this case, the ArrayList would simply store them as Nan values. + +Step 4. minMaxPointFinder() is called to calculate the coordinates of the minimum or maximum point of the quadratic equation. +- The x-coordinate of the vertex is equal to `-b/2a`. +- The y-coordinate of the vertex can thus be found by substituting the x-coordinate value into the equation given by `toDo` +- The method then returns a string displaying the coordinates in the form of `(x,y)`. + +Step 5. Then, `printAnswer` is called which would call upon the `UI` class's method: `printQuadraticAnswer(ArrayList)`. +- If the ArrayList contains NaN values, it would print `x is imaginary.` +- If the ArrayList contains Double data types, then it would print `x1 = 1st Answer` and `x2 = 2nd Answer`. +- If `a` is negative which means there is a maximum point, the appropriate message would be printed. Else it would print the message for +minimum point. +- The coordinates of the vertex would then be printed. + + +Step 5. If any exceptions are caught in the above steps, `printQuadraticFormulaError` would be called from UI to show an error message +to the user. +
+Sequence Diagram for solving Quadratic Equations +
+ +![img.png](SequenceDiagrams/Quadratic.png) + +
+
+ +### Notes +The Notes feature allows users to input their notes for note-taking purposes +and to keep track of their notes through various functionalities provided by BadMaths. + +This feature is implemented by storing the notes input from users into +the `data/notes.txt` file, and users are able to keep track +of their notes by reading the content from the `data/notes.txt file/`. + +#### Note Class: +The Note class represents a note item, which includes information about the note, +its priority level, its review count, and whether the note has been marked as completed or not. + +##### Class Structure: +The Note class is defined with the following instance variables: + +- `text` (String): the note information +- `reviewCount` (int): the number of times the note has been reviewed +- `isDone` (boolean): whether the note is marked as complete or incomplete +- `priority` (NotePriority.Priority): the priority level of the note + +The class contains the following methods: + +- `Note`: constructor that initializes the instance variables with the given parameters +- `getText`: returns the note's text +- `setText`: sets the note's text to the given value +- `getReviewCount`: returns the number of times the note has been reviewed +- `incrementReviewCount`: increments the review count by 1 +- `getIsDone`: returns whether the note is marked as done or not +- `getIsDoneIcon`: returns a string representation of the completion status ("Y" for done, "N" for not done) +- `markAsDone`: marks the note as done +- `markAsNotDone`: marks the note as not done +- `getPriority`: returns the priority of the note +- `setPriority`: sets the priority of the note to the given value +- `setReviewCount`: sets the review count to the given value +- `toString`: returns a string representation of the note in the format `[priority][completion status][review count]text`. + +#### Notes Text: +The `notes.txt` file is a text file that contains the list of Notes stored by users using `BadMaths`. +It is located in the `data` directory of the project. +The purpose of this file is to allow users to keep a list of their notes stored +and to display their notes item stored as and when is needed for their educational purposes. + +##### Format: +The `notes.txt` file format consists of four fields separated by a tab character `\t`: priority, status, count, and text. +These fields provide information about each note in the file. + +###### Priority: +The priority field indicates the importance level of a certain note. It can have one of the three values: `HIGH`, `MEDIUM`, or `LOW`. +This field helps users quickly identify notes that require more attention. + +###### Status: +The status field indicates the current state of the note. It can have one of two values: `done`, denoted by `Y`, or `pending`, denoted by `N`. +If a note has been completed, the status field should be set to `done`. If a note is still in progress, the status field should be set to `pending`. + +###### Count: +The count field indicates the number of times the note has been reviewed. Each time a note is reviewed, the count field is incremented by one. +This allows the user to keep track of how many times a note has been reviewed. + +###### Text: +The text field contains the actual content of the note. This can be any text-based information provide by the user. + +###### Example of information displayed in `notes.txt`: + +```` +HIGH Y 1 Note_Item_1 +MEDIUM N 2 Note_Item_2 +LOW Y 3 Note_Item_3 +```` + +### Storage + +#### NotesFileParser Class + +The `NotesFileParser` class is responsible for loading notes from a file and returning them as an `ArrayList` of `Note` objects. +It contains a single public static method `loadFile()` which takes the file path as a parameter and returns an `ArrayList`. + +Step 1. The method starts by creating a new `ArrayList` of `Note` objects named `notes` that will contain the notes read from the file. + +Step 2. The `loadFile()` method then opens the file specified by the path parameter using a `Scanner` object and reads each +line of the file in a loop using the `hasNextLine` and `nextLine` methods of the `Scanner` object. + +Step 3. For each line, the method calls the `parseNoteString` method of the `NoteParser` class to convert the `String` representation of the note into a `Note` object. + +Step 4. The `Note` object is then added to the `ArrayList` of `Note` objects. + +Step 5. If the file is not found, the method catches the `FileNotFoundException` and prints the exception message. + +Step 6. If the file format is invalid, the method catches the `InvalidFormatException` and calls the `responseHandler` method of the `InvalidNotesFileHandler` class +to prompt the user to reset the file or exit the program. + +Step 7. The method returns the `ArrayList` of `Note` objects. + +#### NoteParser Class + +The `NoteParser` class is responsible for parsing a string representation of a note into a `Note` object. It contains a single public static method `parseNoteString()` which takes a `String` object as a parameter and returns a `Note` object. + +Step 1. The method starts by splitting the `noteString` into four parts using the `split` method with a tab `\t` as the separator. +This creates an array of four elements, each containing one part of the note string. If the length of the resulting array is not `4`, +the method throws an `InvalidFormatException`. + +Step 2. If the length of the resulting array is `4`, the method continues to parse the four parts of the note string. + +a. The first part represents the `priority` of the note, and it is read as a string. The method checks if the string is one of the valid priority values (`LOW`, `MEDIUM`, `HIGH`), +and if not, it throws an `InvalidFormatException`. If the string is valid, the method converts it to a `NotePriority.Priority` enum value. + +b. The second part represents the `status` of the note (whether it is done or not), and it is read as a string. The method checks if the string is one of the valid status values (`Y`, `N`), +and if not, it throws an `InvalidFormatException`. If the string is valid, the method converts it to a `boolean` value (true if the string is `Y`, false otherwise). + +c. The third part represents the `review count` of the note, and it is read as a string. The method tries to parse the string as an integer using the `Integer.parseInt` method. +If the string cannot be parsed as an integer, the method throws an `InvalidFormatException`. If the string is valid, the method stores the integer value in a variable named `reviewCount`. + +d. The fourth part represents the `text` of the note, and it is read as a string. + +Step 3. If the four parts of the note string are valid, the method creates a new `Note` object with `text` and `priority`, +updates its `status` and `review count` respectively with parsed values, and returns the `Note` object. + +Step 4. If `InvalidFormatException` is caught during the parsing process, the method throws the exception to the calling method to handle it. + +#### InvalidNotesFileHandler + +The `InvalidNotesFileHandler` contains a single public static method called `responseHandler`, +which takes in two arguments: a `String` representing the path to the file with invalid format and an `ArrayList` of `Note` objects that will be cleared if the user confirms the file reset. + +Step 1. The method starts by creating a `Scanner` object to read user input from the console. + +Step 2. The method prints a message to notify the user that the notes file seems to be corrupted and prompts the user to confirm to reset the file. + +Step 3. The method reads the user's input and trims it to remove any leading or trailing white spaces. +It also converts the input to lowercase to simplify the input comparison. + +Step 4. If the user confirms to reset the file by typing `y`, the method clears the file contents by creating a `PrintWriter` object and passing the file path to it. +The `print` method of the PrintWriter object is then called with an empty string to clear the contents of the file. The `close` method is called to close the `PrintWriter` object. + +Step 5. The method also clears the `ArrayList` of `Note` objects. + +Step 6. The method prints a message to notify the user that the file contents have been reset successfully and prompt the user to continue using the application. + +Step 7. If the user types `n` to not reset the file, the method prints a message to notify the user to ensure the file status before using the application. +The program will exit in `10` seconds using the `Timer` class and `TimerTask` class if there is no user response in `10` seconds. + +Step 8. If the user types any input other than `y` or `n`, the method prints a message to notify the user of invalid input and recursively calls the `loadFile` method with the same file path argument to ask the user again. + +
+Sequence Diagram for File Loading +
+ +![load_sequence_diagram.png](SequenceDiagrams%2Fload_sequence_diagram.png) +![note_parser_sequence_diagram.png](SequenceDiagrams%2Fnote_parser_sequence_diagram.png) +![invalid_file_handler_sequence_diagram.png](SequenceDiagrams%2Finvalid_file_handler_sequence_diagram.png) + +
+
+ +#### NotesFileWriter Class + +The `NotesFileWriter` contains a single public static method called `saveFile`, which takes in two arguments: +a `String` representing the path to the file to be written, and an `ArrayList` of `Note` objects that will be written to the file. + +Step 1. The method starts by creating a `File` object representing the file to be written based on the provided path. + +Step 2. The method check whether the file exists or not. If the file does not exist, the method creates the file and its parent directory when necessary. + +Step 3. The method creates a `FileWriter` object and passes the file path to it. + +Step 4. The `fileContent` method of `NotesFileContentManager` class is called. +It takes in the `ArrayList` of `Note` objects and returns a `String` representing the contents need to be written to the file. + +Step 5. The `String` returned from `fileContent` is then written to the file using the `write` method of the `FileWriter` object. + +Step 6. The `FileWriter` is closed using `close` method. + +#### NotesFileContentManager Class + +The `NotesFileContentManager` class contains a static method `fileContent` that takes an `ArrayList` of `Note` objects and returns a formatted string that can be written to a file. + +Step 1. The method starts by creating a `StringBuilder` object named `content` to accumulate the formatted string. + +Step 2. The method then loops through each `Note` object in the input `ArrayList` using a for-each loop: + +Step 3. For each `Note` object, the method extracts the `priority`, `status`, `review count`, and `text`, +and appends them to the content string in the expected format: `priority` `\t` `stauts` `\t` `review count` `\t` `text` + +Step 4. The `StringBuilder` object is converted to a string using the `toString` method and returned by the `f`ileContent` method: + +#### NotesFileCleaner Class + +The `NotesFileWriter` class contains a single public static method called `clearFile`. +Its purpose is to clear the content of a file located at a specified path. + +Step 1. The method takes a string parameter that represents the path to the file that needs to be cleared. + +Step 2. A new `FileWriter` object is created using the specified path. + +Step 3. The `write` method of the `FileWriter` object is called with an empty string as the argument. This clears the content of the file. + +### Store class: +The `Store` class takes in inputs from users and store these notes into the +`notes.txt` file. It consists of a static boolean method that detects invalid `todo` input entered by users +and a public method that stores notes to the notes list. + +Step 1. The `Store` class takes in two variables `notes` and `todo`, and constructs a new `Store` instance +using the two variables. + +Step 2. The `isInvalidTodo` static boolean method will check for the validity of the `todo` string input. + +Step 3. The `storeNotes` public method will then store the note item input by users into the notes list. + +
+Sequence Diagram for Store +
+ +![img.png](SequenceDiagrams/Store_sequence_diagram.png) + +
+
-{Describe the target user profile} +### List class: +The `List` class takes in inputs from users and list either all the notes stored in notes list or a specific note +based on the index that users have input to BadMaths. +It consists of a few public boolean method that detects invalid `todo` input entered by users, +detects if `todo` provided is not an integer, and detects if `todo` provided is an invalid index. +It also consists of a public method that list notes stored in notes list. + +Step 1. The `List` class takes in two variables `notes` and `toDo`, and constructs a new `List` instance +using the two variables. + +Step 2. The `isInvalidTodo`, `isInvalidIndex` and `isAnInt` boolean method will check for the validity of the `todo` string input. + +Step 3. The `listNotes` public method will then list either all the notes stored in notes list or a specific note +based on the index that users have input to BadMaths. + + +### Delete class: +The `Delete` class takes in inputs from users and deletes a specific note in the notes list +based on the index that users have input to BadMaths. +It consists of two static boolean methods that detects whether `todo` provided by users +is not an integer, and detects whether `todo` provided is an invalid index. +It also consists of a public method that deletes notes stored in notes list. + +Step 1. The `Delete` class takes in two variables `notes` and `toDo`, and constructs a new `Delete` +instance using the two variables. + +Step 2. The `isInvalidIndex` and `isAnInt` static boolean methods will check for the +validity of the `toDo` string input by users. + +Step 3. The `deleteNotes` public method will then delete the specific note in the notes list +based on the index that users have input to BadMaths. + +### CommandHistory class: +The `CommandHistory` class stores a list of all inputs entered by users during the current programme run session. +It consists of two public class methods, `storeCommand` and `displayHistory`. + +Step 1. An ArrayList `historyCommand` is created at the start. +The `CommandHistory` class takes in an ArrayList `historyCommand`, +and constructs a new `CommandHistory` instance using that ArrayList. + +Step 2. The `storeCommand` public method adds the input command given by users into the +`historyCommand` ArrayList. + +Step 3. The `displayHistory` public method outputs a list of past commands entered by users during +the current programme run. + +### Command class: +The `Command` class takes in inputs from users +and executes the relevant functions based on the inputs of the users. It consists of +public methods such as `isInvalidTodo` and `executeCommand`. + +Step 1. The `Command` class takes in a `command` and a `toDo` item and +based on both of these inputs, the `Command` class then identifies the relevant functions +to be executed. + +Step 2. The `executeCommand` method does the executing of the relevant functions depending on the `command` that +is being input by users. There are several functionalities provided in the `executeCommand` for users, including but +not limited to the Storing and Deleting of Notes, Marking and Unmarking of notes items as completed or incomplete, and +the searching for notes through keywords or priorities of the notes. + +### Ui class: +The `Ui` class consists of several static methods which are used +to print user interface messages when users are performing the +operations of BadMaths such as the notes and calculation operations and functionalities. + +The methods that are in the Ui class are as follows: +`printIncorrectFormatEntered()`: prints out a warning message to alert the +user that an incorrect command format for badMaths has been entered. + +`printNegativeAmplitudeEntered()`: prints out a warning message to alert that the user has input a negative amplitude. + +`printAmplitude(double amplitude)`: prints out the amplitude of the Mathematical function provided by the user. + +`printPhase(double phase)`: prints out the phase angle of the Mathematical function provided by the user. + +`printVerticalShift(double verticalShift)`: prints out the vertical shift of the Mathematical function provided by the user. + +`printFrequency(Double freq)`: prints out the frequency of the Mathematical function provided by the user. + +`printInvalidNumberEntered()` : prints out a warning message to alert that the user has input a non-numerical input. + +`printMark(String text)`: prints out a message indicating that a note has been marked as done by the user. + +`printUnmark(String text)`: prints out a message indicating that a note has been unmarked as incomplete by the user. + +`printAddNote(String text, int size)`: prints out a message indicating that a note has been added by the user +and displays to the user the total current number of notes stored in the list. + +`printDelete(String text, int size)`: prints out a message indicating that a note has been removed by the user +and displays to the user the total current number of notes stored in the list. + +`printNotes(ArrayList notes)`: prints out all the notes currently stored in the list by the user. + +`printSpecificNote(int index, ArrayList notes)`: prints out a specific note in the list based on +an index provided by user. + +`printFindNotes(ArrayList notes)`: prints out all the notes in the list +that matches the keyword provided by the user. + +`printPriority(int index, ArrayList notes)`: prints out a message indicating to the user that the +priority of a note item has been changed based on the user's preference. + +`printNotesByReviewCount(ArrayList notes)`: prints out all the notes sorted based on the number of +review counts for each note item in a list format. + +`printNotesByPriority(ArrayList notes)`: prints out all the notes sorted based on the +priority (HIGH, MEDIUM, LOW) of the note items in a list format. + +### NotePriority class: +The `NotePriority` class is utilised to set the priority level (LOW, MEDIUM, HIGH) +of the notes stored in the Notes List by users. + +### Help +The Help feature allows users to view possible options by calling `Help.` which reads the content stored in the HelpManual.txt. + +The feature implemented involves reading the content from HelpManual.txt file and logging the result of read operation using the Java Logging API. + +#### HelpManual text: +`HelpManual.txt` is a text file that contains the help manual for BadMaths. It is located in the `src/main/resources` directory of the project. +The purpose of this file is to provide users with helpful instructions on how to operate BadMaths. + +#### HelpManual class: +Step 1. Define the HelpManual class: The HelpManual class is defined as a public class with two static fields: filePath and logFilePath. +These fields contain the file path of the HelpManual.txt file and the name of the log file, respectively. + +Step 2. Setting up the Logger: The Logger is set up in the HelpManual class using the Java Logging API. +The `setUpLogger()` method resets the LogManager, sets the logger's level to ALL, and creates a log file if it does not already exist. +This method is called before the `readHelpManual()` method to ensure that the logger is properly configured. + +Step 3. Reading the file: +The `readHelpManual()` method is implemented to read the content from the HelpManual.txt file. +It first calls the setUpLogger() method to configure the logger. Then it obtains an InputStream object that reads the content from the +file using the `getResourceAsStream()` method. Before reading the file, the `readHelpManual()` method asserts that the input stream is not null to ensure that the file exists and is readable. +The file is then read line by line using a BufferedReader object, and each line is appended to a StringBuilder object. Otherwise, +the `getResourceAsStream()` method will return a null value, and an `AssertionError` will be thrown. + +Step 4. Logging the result: After reading the file, the `readHelpManual()` method closes the BufferedReader and InputStream +objects and logs the success or failure of the read operation using the logger. If the read operation is successful, a message +is logged to the console and log file indicating that the HelpManual file was successfully read. If an exception occurs during +the read operation, an error message is logged to the console and log file. + +### Graph +The Graph feature allows users to analyse basic Trigonometry signals by calling `startGraphAnalysis()` which +creates a new instance of `TrigoGraphAnalyser` named `analyser`. + +Below is an example usage scenario and how the `Graph` feature behaves at each step. + +When user enters an input: +``` +Graph. 2*sin(2*x+5)-1 +``` +#### Parser class, Command class: +Step 1. Parser class will split the input into `Graph.` and `2*sin(2*x+5)-1`, which are `command` and `toDo` respectively. +The command class creates a new instance of `TrigoGraph` and pass in `toDo` as a parameter for the constructor. It +then executes `trigoGraph.startGraphAnalysis()`based on `command` using switch-case statements. + +#### TrigoGraph class: +
+Sequence Diagram for TrigoGraph class +
+ +![img_1.png](SequenceDiagrams/GraphSequence.png) + +
+
+
+
+Class Diagram for TrigoGraph class +
+ +![img_1.png](ClassDiagrams/graph_class_diagram.png) + +
+
+
+Step 2. Constructor for the TrigoGraph class takes in `2*sin(2*x+5)-1` and assigns it to `trigoEqn` of type String. When `startGraphAnalysis()` +is called from the command class, a new instance of `TrigoGraphAnalyser` called `analyser` is created in TrigoGraph, which accepts `trigoEqn` +as the parameter. + +Step 3. When `analyser.canStartAnalyser()` is true, it will print out the amplitude, frequency, phase and vertical shift +to the user using the Ui class. Each of the method calls to the Ui class requires an input of type double which can +be achieved by calling `analyser.getAmplitude()`, `analyser.getFreq()` and so on. + +#### TrigoGraphAnalyser class: +Step 4. In the `canStartAnalyser()` method, the trigo equation is split into various parts, and there +is a method call to create `setUpLogger()` to log exceptions when user enters +invalid trigo equation. `canStartAnalyser()` returns false if an exception is reached, else it returns true. + +Step 5. `canStartAnalyser()` calls `splitAmplitudeFromTrigoEqn()`. This method will split +the input into `2` and `sin(2*x+5)-1` using `*` as the regex. + +Step 6. 2 tests are ran within `splitAmplitudeFromTrigoEqn()` to check for negative amplitude and multiple asterisk. +In this case, both checks will return false. + +Step 7. The separated String is passed into `String[] amplitudeAndEqn`. The string is then passed into `findAmplitude` +to determine the amplitude. In `findAmplitude(eqn)`, `isAmplitudeEqualsToOne(eqn[0])` will check if the input string +starts with `cos`, `sin` or `tan`, where `eqn[0]` is `2` and `eqn[1]` is `sin(2*x+5)-1`. +If this is true, 1.0 will be assigned to `amplitude`. Else, string `2` will be converted to double `2.0` and assigned to +`amplitude`. + +Step 8. After finding `amplitude`, `canStartAnalyser()` calls `splitTrigoAndVerticalShift(amplitudeAndEqn[1])`, where +`amplitudeAndEqn[1]` is `sin(2*x+5)-1`. `splitTrigoAndVerticalShift` splits `sin(2*x+5)-1` into `sin(2*x+5` and `-1` +based on `)` and returns the separated string to `trigoAndVerticalShift`. + +Step 9. `canStartAnalyser()` calls `findVerticalShift()` which takes in `sin(2*x+5` and `-1` as a string [] parameter. +In `findVerticalShift()`, method call to `isVerticalShiftZero(-1)` is false and thus, +`-1` is converted to double `-1.0` and assigned to `vertricalShift`. + +Step 10. In `canStartAnalyser()`, string `trigo` is assigned `sin(2*x+5`. + +Step 11. `canStartAnalyser()` calls `splitTrigoIntoPhasors()` and takes in `trigo` as the parameter. In `splitTrigoIntoPhasors()`, +`startPosOfPhase` is 4 while `endPosOfPhase` is 9. A new String variable `phase` is assigned the substring of trigo from +4 to 9, resulting in `2*x+5`. `splitPhasorsIntoFreq()` is called and it accepts string `2*x+5` as input. + +Step 12. In `splitPhasorsIntoFreq()`, `findFreqForPlus()` is called which takes in string `2*x+5` as input. + +Step 13. In `findFreqForPlus()`, `2*x+5` is split into `2*x` and `5` using the split function with `+` as the regex. +`findPhase()` which accepts `5` and a boolean `false` as parameters, and `findFreq()` which accepts `2*x` and a boolean `false` are called. + +Step 14. In `findPhase()`, `phase` is assigned the double of `5` and in `findFreq()`, `2*x` is substring into `2` and converted +to double `2.0`. `Freq` is assigned the double value of `2.0 / (2 * Math.PI)`. + +Step 15. Finally, `canStartAnalyser()` reaches the end and returns true. + +#### TrigoGraphVisualiser class: +Step 16. The `TrigoGraphVisualiser` extends JPanel and overrides the `paintComponent()` method in JComponent. + +Step 17. A new instance of `TrigoGraphVisualiser` is created in `startGraphAnalysis` to assign corresponding values to the amplitude, phase, frequency, +vertical shift, and the trigonometric function in `TrigoGraphVisualiser`. Next, `startVisualiser()` is called to create the frame +for the graph. + + +Step 18. The frame is set half of the screen size using `setSize()` and `getScreenSize()`. + +Step 19. When the frame is created, `paintComponent` will be called. It sets up the scale factors which will scale the values +generated by the trigo function to that of the frame. It the sets up the x and y axis using `g.drawLine()`. + +Step 20. Using the switch-case statements. `drawSinCurve()` will be executed and amplitudes will be labelled on the axis. +The for loop will run from `xMin` to `xMax`, which are the negative frequency and positive frequency for one period respectively. +After getting the y value from the output of the sin equation, both *x* and *y* are scaled to *xPixel* and *yPixel* respectively. A horizontal line is drawn at every pixel, which +eventually forms the sine graph. + +### Matrix + +The Matrix feature supports various basic matrix calculations below: +* Matrix multiplication +* Matrix element wise product +* Matrix addition +* Matrix subtraction + +With calling `calculator.run()`, BadMaths parses the user's input and conducts the given command. + +If you want to see the overall flow of the Matrix part, click the toggle button below: + +
+See the Class Diagram +
+ +![img.png](ClassDiagrams/MatrixClassDiagram.png) + +
+
+ +
+See the Sequence Diagram +
+ +![img.png](SequenceDiagrams/MatrixDG.png) + +
+
+ +
+ +Below is an example usage scenario and how the `Matrix` feature behaves at each step. + +When user enters an input: +``` +Matrix [1,2;3,4] .* [5,6;7,8] +``` + +#### Calculator class + +step 1. `run()` function in `Calculator.class` firstly get `toDo` as the argument which is `[1,2;3,4] .* [5,6;7,8]` in the above example. +This `run()` function sequentially parses this string, executes the command and shows the result matrix to users. + +#### Parser class + +step 2. Firstly, `run()` function pass the `toDo` string to `parse()` function defined in `Parser.class`. +This `parse()` function firstly identifies the type of the operator of this command with referring `toDo` string. +And then, it divides the cases with this identified type with using `switch` statement. + +#### Execute class + +step 3. According to each case divided by operator types in the previous step, +`parse()` function calls corresponding function defined in `Execute.class` for conducting calculation. +In the case of the above example, `parse()` function calls `executeMul()` defined in `Execute.class` since the type of the +operator is matrix multiplication. Finally, it passes the `toDo` string to `executeMul()` function as the argument. + +step4. `executeMul()` function firstly extracts two operands from `toDo` string. And pass these two operands to `executeTranspose()` +in `Execute.class` respectively. + +step 5. In this `executeTranspose()` function, function checks whether there is transpose mark in the given operand, and parses this +operand which is string type into `Tensor2D` type so that this operand could be internally calculated. In this parsing phase, +`parseMatrix()` function defined in `Parser.class` is used. This function finally outputs this `Tensor2D` type operand to +`executeMatrix()` function. + +step 6. Regarding these two operands with `Tensor2D` type, `executeMul` function calls `mul()` function defined in `calculate.class`. + +#### Calculate class + +step 7. `mul()` function defined in `Calculate.class` internally conducts matrix multiplication with nested for-loop +and outputs the result which is `Tensor2D` type. + +step 8. This result is sequentially returned to `executeMul()`, `parse()` and `run()` function. Finally in the `run()` function, +the result is printed in terminal. + + +## Product Scope +### Target user profile +Mathematics students who are studying and practicing Mathematical topics on Matrices, Quadratic Equations +or Sinusoidal Signals. ### Value proposition -{Describe the value proposition: what problem does it solve?} +Students can access mathematical tools like matrix calculator, quadratic equation solver, and trigonometry graph analyser +quickly when studying. Concurrently, students are also able to make use of the Notes function in BadMaths +to do note-taking and to keep track of their notes through the use of various Notes features in BadMaths. + +This integrated mathematical tool aims to help users solve their mathematical doubts or clarifications quickly which saves time, as they do not +have to search for different tools online. + ## User Stories -|Version| As a ... | I want to ... | So that I can ...| -|--------|----------|---------------|------------------| -|v1.0|new user|see usage instructions|refer to them when I forget how to use the application| -|v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list| +| Version | As a ... | I want to ... | So that I can ... | +|---------|-----------------------------------------|------------------------------------------------------------|-----------------------------------------------------------------------------------------| +| v1.0 | student studying Linear Algebra | be able to check my answers for Matrix multiplications | ensure that the method I am using for manual calculations is correct | +| v1.0 | student overwhelmed by math information | be able to store custom notes | refer to them whenever I want to refresh my memory | +| v1.0 | student studying Signals and Systems | be able to find the characteristics of trigo graphs easily | save time when doing my tutorials and not have to worry about the tedious calculations | +| v2.0 | secondary school maths student | be able to solve quadratic equations | complete my homework as fast as possible and as correctly as possible | + ## Non-Functional Requirements -{Give non-functional requirements} +* Notes can be ported when program starts on a new device. +* The program should terminate and print an error message when it takes to long to process user inputs. +* The program should be straightforward and concise; No doubts on how to use the program. +* Capabilities of the program are made known to the users. +* Program is to implement features related to studying and maths only. E.g. A step tracker that tracks number of steps +walked is out of scope. ## Glossary -* *glossary item* - Definition +* *x* - input to the trigonometric function, sin(freqInHz* *x*+phase). +* *y* - output of the trigonometric function above. +* *xPixel* - *x* value is scaled to position of the x position of the screen. +* *yPixel* - *y* value is scaled to position of the y position of the screen. ## Instructions for manual testing -{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} +- Download the latest release of BadMaths [here](https://github.com/AY2223S2-CS2113-F10-2/tp/releases). +- Save the java file to a new folder. +- Open command prompt by typing `cmd` in the Windows search bar. +- Navigate to the folder via `cd "folder path"`. (eg. `cd C:\Users\your_name\Desktop\BadMaths`). +- Type `java -jar BadMaths.jar` to run BadMaths. +- Follow the [User Guide](https://github.com/AY2223S2-CS2113-F10-2/tp/blob/master/docs/UserGuide.md) to begin testing. diff --git a/docs/ImagesForUserGuide/Graph_eg_output_1.png b/docs/ImagesForUserGuide/Graph_eg_output_1.png new file mode 100644 index 0000000000..2436201a70 Binary files /dev/null and b/docs/ImagesForUserGuide/Graph_eg_output_1.png differ diff --git a/docs/ImagesForUserGuide/Graph_eg_output_2.png b/docs/ImagesForUserGuide/Graph_eg_output_2.png new file mode 100644 index 0000000000..62da5a1b6c Binary files /dev/null and b/docs/ImagesForUserGuide/Graph_eg_output_2.png differ diff --git a/docs/ImagesForUserGuide/Graph_eg_output_3.png b/docs/ImagesForUserGuide/Graph_eg_output_3.png new file mode 100644 index 0000000000..ef1fca34c5 Binary files /dev/null and b/docs/ImagesForUserGuide/Graph_eg_output_3.png differ diff --git a/docs/Profile pictures/Seungjun_pic.jpg b/docs/Profile pictures/Seungjun_pic.jpg new file mode 100644 index 0000000000..82544708ae Binary files /dev/null and b/docs/Profile pictures/Seungjun_pic.jpg differ diff --git a/docs/Profile pictures/khooyourun_pic.png b/docs/Profile pictures/khooyourun_pic.png new file mode 100644 index 0000000000..a9dee411d5 Binary files /dev/null and b/docs/Profile pictures/khooyourun_pic.png differ diff --git a/docs/Profile pictures/wilson_pic.png b/docs/Profile pictures/wilson_pic.png new file mode 100644 index 0000000000..3cd59a1755 Binary files /dev/null and b/docs/Profile pictures/wilson_pic.png differ diff --git a/docs/Profile pictures/yc_pic.png b/docs/Profile pictures/yc_pic.png new file mode 100644 index 0000000000..db46ce8b55 Binary files /dev/null and b/docs/Profile pictures/yc_pic.png differ diff --git a/docs/Profile pictures/ziqiuzeng_pic.png b/docs/Profile pictures/ziqiuzeng_pic.png new file mode 100644 index 0000000000..5959c52f02 Binary files /dev/null and b/docs/Profile pictures/ziqiuzeng_pic.png differ diff --git a/docs/README.md b/docs/README.md index bbcc99c1e7..2caa21b3ba 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,44 @@ -# Duke +# _BadMaths_ ➕➖✖️➗ + +BadMaths is an integrated study tool that performs Mathematical Operations and contains various features for note-taking. + +To help you get started, our team has put together this user guide to guide you on the steps to operate BadMaths for your study woes. + +## Setting up + +Prerequisites: JDK 11 (use the exact version), update Intellij to the most recent version. + +1. **Ensure Intellij JDK 11 is defined as an SDK**, as described [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk) -- this step is not needed if you have used JDK 11 in a previous Intellij project. +2. Download the latest JAR release [here](https://github.com/AY2223S2-CS2113-F10-2/tp/releases). +3. Copy the JAR file into an empty folder. +4. Open up a command window in that folder and run the following command: +``` +java -jar BadMaths.jar +``` +If the set-up is correct, you should see the following: +``` +____ _ __ __ _ _ +| _ \ | | | \/ | | | | | +| |_) | __ _ __| | | \ / | __ _| |_| |__ ___ +| _ < / _` |/ _` | | |\/| |/ _` | __| '_ \/ __| +| |_) | (_| | (_| | | | | | (_| | |_| | | \__ \ +|____/ \__,_|\__,_| |_| |_|\__,_|\__|_| |_|___/ +You can type 'Help' to learn what I can do for you :) +``` + +## Features (v2.1) +#### Monday, April 10, 2023 + +1. **Basic mathematical operations** + - Analyse trigonometry equations / sinusoidal signals + - Solve quadratic equations + - Solve matrix calculations +2. **Notes taking** + - Store, delete and list notes + - Mark or unmark the notes as done + - Rank and display notes based on priority + - Find notes based on keywords -{Give product intro here} Useful links: * [User Guide](UserGuide.md) diff --git a/docs/SequenceDiagrams/GraphSequence.png b/docs/SequenceDiagrams/GraphSequence.png new file mode 100644 index 0000000000..c351f822df Binary files /dev/null and b/docs/SequenceDiagrams/GraphSequence.png differ diff --git a/docs/SequenceDiagrams/MatrixDG.png b/docs/SequenceDiagrams/MatrixDG.png new file mode 100644 index 0000000000..baa11433e2 Binary files /dev/null and b/docs/SequenceDiagrams/MatrixDG.png differ diff --git a/docs/SequenceDiagrams/Quadratic.png b/docs/SequenceDiagrams/Quadratic.png new file mode 100644 index 0000000000..9efc2b5a5e Binary files /dev/null and b/docs/SequenceDiagrams/Quadratic.png differ diff --git a/docs/SequenceDiagrams/Store_sequence_diagram.png b/docs/SequenceDiagrams/Store_sequence_diagram.png new file mode 100644 index 0000000000..9cef22530d Binary files /dev/null and b/docs/SequenceDiagrams/Store_sequence_diagram.png differ diff --git a/docs/SequenceDiagrams/invalid_file_handler_sequence_diagram.png b/docs/SequenceDiagrams/invalid_file_handler_sequence_diagram.png new file mode 100644 index 0000000000..2f4c9598d3 Binary files /dev/null and b/docs/SequenceDiagrams/invalid_file_handler_sequence_diagram.png differ diff --git a/docs/SequenceDiagrams/load_sequence_diagram.png b/docs/SequenceDiagrams/load_sequence_diagram.png new file mode 100644 index 0000000000..5e9defc4b8 Binary files /dev/null and b/docs/SequenceDiagrams/load_sequence_diagram.png differ diff --git a/docs/SequenceDiagrams/note_parser_sequence_diagram.png b/docs/SequenceDiagrams/note_parser_sequence_diagram.png new file mode 100644 index 0000000000..8728cb6271 Binary files /dev/null and b/docs/SequenceDiagrams/note_parser_sequence_diagram.png differ diff --git a/docs/UmlFiles/MatrixClassDiagram.puml b/docs/UmlFiles/MatrixClassDiagram.puml new file mode 100644 index 0000000000..d906af23f1 --- /dev/null +++ b/docs/UmlFiles/MatrixClassDiagram.puml @@ -0,0 +1,106 @@ +@startuml +'https://plantuml.com/class-diagram + +!pragma layout smetana + +class Calculator { + + logger : Logger + + run() +} + +class Parser { + + check : ExceptionChecker + + ep : ExceptionPrinter + + parse() : Tensor2D + + parseOp() : CalType + + parseMatrix() : Tensor2D +} + +class Execute { + + execute() : Tensor2D + + executeMul() : Tensor2D + + executeAdd() : Tensor2D + + executeSub() : Tensor2D + + executeDot() : Tensor2D + + executeTranspose() : Tensor2D +} + +class Calculate { + + check : ExceptionChecker + + ep : ExceptionPrinter + + logger : Logger + + mul() : Tensor2D + + add() : Tensor2D + + sub() : Tensor2D + + dot() : Tensor2D +} + +class Tensor2D { + + tensor : int[][] + + shape : Shape + + shape() : Shape + + row() : int + + column() : int + + tensor() : int[][] + + get() : int + + t() : Tensor2D + + toString() +} + +class Shape { + + row : int + + column : int + + getRow() : int + + getColumn() : int + + toString() +} + +class ExceptionChecker{ + + checkShapeMismatch() + + checkUnknownOperator() + + checkMatrixFormat() +} + +class ExceptionPrinter{ + + printShapeMismatchExceptionLog() + + printUnknownOperatorExceptionLog() + + printMatrixShapeExceptionLog() + + printMatrixFormatExceptionLog() + + printMatrixNumericExceptionLog() +} + +class Ui{ + + printResult() +} + +class MatrixFormatException +class MatrixShapeException +class ShapeMismatchException +class UnknownOperatorException + +abstract Tensor { + + shape() + + toString() +} + +Ui <-- "print 0..1"Calculator +Parser <-- "parser 0..1"Calculator +Execute <-- "execute 0..1"Parser +Parser <.. Execute +Tensor2D <-- "2D tensor 1..*"Parser +Tensor2D "2D tensor 1..*"<-- Execute +Tensor2D "2D tensor 1..*"<.. Calculate +Calculate "calculate 0..1"<-- Execute +Tensor2D "2D tensor 1..*"<-- Tensor2D +Shape "shape 1"<-- Tensor2D +Tensor2D <|-- Tensor +ExceptionChecker "0..1"<-- Parser +ExceptionChecker "0..1"<-- Calculate +ExceptionPrinter "0..1"<-- Parser +ExceptionPrinter "0..1"<-- Calculate +MatrixFormatException "exception 0..1"<..ExceptionChecker +MatrixShapeException "exception 0..1"<..ExceptionChecker +ShapeMismatchException "exception 0..1"<..ExceptionChecker +UnknownOperatorException "exception 0..1"<..ExceptionChecker + +@enduml \ No newline at end of file diff --git a/docs/UmlFiles/MatrixDG.puml b/docs/UmlFiles/MatrixDG.puml new file mode 100644 index 0000000000..a2f7bdaf85 --- /dev/null +++ b/docs/UmlFiles/MatrixDG.puml @@ -0,0 +1,112 @@ +@startuml +'https://plantuml.com/sequence-diagram + +Command -> Calculator : run() +activate Calculator + +Calculator --> Ui : Ui() +activate Ui +Ui --> Calculator +deactivate Ui + +Calculator --> Parser : Parser() +activate Parser +Parser --> Calculator +deactivate Parser + +Calculator -> Parser : parse(toDo) +activate Parser + +Parser --> Execute : Execute() +activate Execute +Execute --> Parser +deactivate Execute + +alt ADD + Parser -> Execute : executeAdd(command) + activate Execute + + Execute --> Calculate : Calculate() + activate Calculate + Calculate --> Execute + deactivate Calculate + + Execute -> Execute : executeTranspose(operator[0]) + Execute -> Execute : executeTranspose(operator[1]) + + Execute -> Calculate : add(t1, t2) + activate Calculate + Calculate -> Execute : result + deactivate Calculate + + Execute -> Parser : result + deactivate Execute +else SUB + Parser -> Execute : executeSub(command) + activate Execute + + Execute --> Calculate : Calculate() + activate Calculate + Calculate --> Execute + deactivate Calculate + + Execute -> Execute : executeTranspose(operator[0]) + Execute -> Execute : executeTranspose(operator[1]) + + Execute -> Calculate : sub(t1, t2) + activate Calculate + Calculate -> Execute : result + deactivate Calculate + + Execute -> Parser : result + deactivate Execute +else MUL + Parser -> Execute : executeMul() + activate Execute + + Execute --> Calculate : Calculate() + activate Calculate + Calculate --> Execute + deactivate Calculate + + Execute -> Execute : executeTranspose(operator[0]) + Execute -> Execute : executeTranspose(operator[1]) + + Execute -> Calculate : mul(t1, t2) + activate Calculate + Calculate -> Execute : result + deactivate Calculate + + Execute -> Parser : result + deactivate Execute +else DOT + Parser -> Execute : executeDot() + activate Execute + + Execute --> Calculate : Calculate() + activate Calculate + Calculate --> Execute + deactivate Calculate + + Execute -> Execute : executeTranspose(operator[0]) + Execute -> Execute : executeTranspose(operator[1]) + + Execute -> Calculate : dot(t1, t2) + activate Calculate + Calculate -> Execute : result + deactivate Calculate + + Execute -> Parser : result + deactivate Execute +end + +Parser -> Calculator : result + + +Calculator -> Ui : printResult(result) +activate Ui +deactivate Ui + +deactivate Calculator + +@enduml \ No newline at end of file diff --git a/docs/UmlFiles/QuadraticClassDiagram.puml b/docs/UmlFiles/QuadraticClassDiagram.puml new file mode 100644 index 0000000000..10b6a255b8 --- /dev/null +++ b/docs/UmlFiles/QuadraticClassDiagram.puml @@ -0,0 +1,29 @@ +@startuml +'https://plantuml.com/class-diagram + +class Quadratic { + + toDo: String + + quadraticFormula(): ArrayList + + minMaxPointFinder(): String + + printAnswer() + + solveQuadratic() +} +class QuadraticParser { + + findA(): double + + findSignOfB(): String + + findStringOfB(): String + + findB(): double + + findSignOfC(): String + + findStringOfC(): String + + findC(): double +} +class Ui { + + printQuadraticFormatError() + + printQuadraticAnswer() +} + +Quadratic <|-- QuadraticParser +Ui <-- Quadratic + + +@enduml diff --git a/docs/UmlFiles/QuadraticSolver.puml b/docs/UmlFiles/QuadraticSolver.puml new file mode 100644 index 0000000000..f6037e19e6 --- /dev/null +++ b/docs/UmlFiles/QuadraticSolver.puml @@ -0,0 +1,44 @@ +@startuml +'https://plantuml.com/sequence-diagram +-> ":Command" +activate ":Command" +":Command" -> ":Quadratic": quadratic.solveQuadratic() +activate ":Quadratic" +":Quadratic" -> ":QuadraticParser" +activate ":QuadraticParser" +activate ":Ui" +":QuadraticParser" -> ":QuadraticParser" : findA() +activate ":QuadraticParser" #FFBBBB +deactivate ":QuadraticParser" +":QuadraticParser" -> ":QuadraticParser" : findB() +activate ":QuadraticParser" #FFBBBB +deactivate ":QuadraticParser" +":QuadraticParser" -> ":QuadraticParser" : findC() +activate ":QuadraticParser" #FFBBBB +deactivate ":QuadraticParser" +":QuadraticParser" --> ":Quadratic" +deactivate ":QuadraticParser" +":Quadratic" -> ":Quadratic": quadraticFormula() +activate ":Quadratic" #FFBBBB +deactivate ":Quadratic" +":Quadratic" -> ":Quadratic": minMaxPointFinder() +activate ":Quadratic" #FFBBBB +deactivate ":Quadratic" +":Quadratic" -> ":Quadratic": printAnswer() +activate ":Quadratic" #FFBBBB +":Quadratic" -> ":Ui": Ui.printQuadraticAnswer() +activate ":Ui" #FFBBBB +":Ui" --> ":Quadratic" +deactivate ":Ui" +deactivate ":Quadratic" +opt Exceptions +":Quadratic" -> ":Ui": printQuadraticFormatError() +activate ":Ui" #FFBBBB +":Ui" --> ":Quadratic" +deactivate ":Ui" +end opt +":Quadratic" --> ":Command" +deactivate ":Quadratic" +deactivate ":Command" +deactivate ":Ui" +@enduml diff --git a/docs/UmlFiles/Store.puml b/docs/UmlFiles/Store.puml new file mode 100644 index 0000000000..b216786691 --- /dev/null +++ b/docs/UmlFiles/Store.puml @@ -0,0 +1,27 @@ +@startuml +'https://plantuml.com/sequence-diagram + +@startuml +title Sequence Diagram for Store +actor User + +User -> ":Store" **: Store(notes, toDo) +User -> ":Store":storeNotes() +activate ":Store" +alt isInvalidTodo(toDo) is "Invalid todo" + ":Store" -> ":Ui" : Ui.printIncorrectFormatEntered() + activate ":Ui" + deactivate ":Ui" + else + ":Store" -> ":notes": notes.add(toDo) + activate ":notes" + deactivate ":notes" + ":Store" -> ":Ui": Ui.printAddNote(toDo, notes.getSize()); + activate ":Ui" + deactivate ":Ui" + ":Store" -> ":NotesFileWriter": NotesFileWriter.saveFile(filePath, notes.getAll()) + activate ":NotesFileWriter" + deactivate ":NotesFileWriter" + end +deactivate ":Store" +@enduml \ No newline at end of file diff --git a/docs/UmlFiles/TrigoGraph.puml b/docs/UmlFiles/TrigoGraph.puml new file mode 100644 index 0000000000..33b1e81809 --- /dev/null +++ b/docs/UmlFiles/TrigoGraph.puml @@ -0,0 +1,75 @@ +@startuml + + +[->":TrigoGraph": startGraphAnalysis() +activate ":TrigoGraph" + +":TrigoGraph"-> ":TrigoGraphAnalyser"**:TrigoGraphAnalyser(trigoEqn) + +activate ":TrigoGraphAnalyser" +":TrigoGraphAnalyser" --> ":TrigoGraph" +deactivate ":TrigoGraphAnalyser" +opt analyser.canStartAnalyser +":TrigoGraph" -> ":TrigoGraph" :getGraphDetails(analyser) +activate ":TrigoGraph" + +":TrigoGraph" -> ":TrigoGraphAnalyser": getAmplitude() +activate ":TrigoGraphAnalyser" +deactivate ":TrigoGraphAnalyser" + +":TrigoGraph" -> ":TrigoGraphAnalyser": getFreq() +activate ":TrigoGraphAnalyser" +deactivate ":TrigoGraphAnalyser" + +":TrigoGraph" -> ":TrigoGraphAnalyser": getPhase() +activate ":TrigoGraphAnalyser" +deactivate ":TrigoGraphAnalyser" + +":TrigoGraph" -> ":TrigoGraphAnalyser": getVerticalShift() +activate ":TrigoGraphAnalyser" +deactivate ":TrigoGraphAnalyser" + +":TrigoGraph" -> ":TrigoGraphAnalyser": getTrigonometry() +activate ":TrigoGraphAnalyser" +deactivate ":TrigoGraphAnalyser" + +":TrigoGraph" -> ":TrigoGraph" +deactivate ":TrigoGraph" + +":TrigoGraph" -> ":TrigoGraph": printGraphDetails() +activate ":TrigoGraph" + +":TrigoGraph" -> ":Ui": printAmplitude(amplitude) +activate ":Ui" +deactivate ":Ui" + +":TrigoGraph" -> ":Ui": printFrequency(frequency) +activate ":Ui" +deactivate ":Ui" + +":TrigoGraph" -> ":Ui": printPhase(phase) +activate ":Ui" +deactivate ":Ui" + +":TrigoGraph" -> ":Ui": printVerticalShift(verticalShift) +activate ":Ui" +deactivate ":Ui" + +":TrigoGraph" -> ":TrigoGraph" +deactivate ":TrigoGraph" + +":TrigoGraph" -> TrigoGraphVisualiser**: TrigoGraphVisualiser(amplitude,phase,frequency,verticalShift,trig) +activate TrigoGraphVisualiser +TrigoGraphVisualiser -->> ":TrigoGraph" +deactivate TrigoGraphVisualiser + +":TrigoGraph" -> TrigoGraphVisualiser: startVisualiser() +activate TrigoGraphVisualiser + +deactivate TrigoGraphVisualiser +end opt + + +deactivate ":TrigoGraph" + +@enduml diff --git a/docs/UmlFiles/UserInputHandlingClassDiagram.puml b/docs/UmlFiles/UserInputHandlingClassDiagram.puml new file mode 100644 index 0000000000..4fac000154 --- /dev/null +++ b/docs/UmlFiles/UserInputHandlingClassDiagram.puml @@ -0,0 +1,33 @@ +@startuml +'https://plantuml.com/class-diagram + +class BadMaths { + + commandChecker() + + main() +} + +class Parser { + # userInput: String + + getCommand(): String + + getToDo(): String +} + +class Ui { + + printIncorrectFormatEntered() + + printWelcomeMessage() +} + +class Command { + # command: String + # toDo: String + + setCommand() + + setToDo() + + executeCommand() +} + +Parser <-- BadMaths +Command "1" <-- BadMaths +Ui "1" <-- BadMaths + + +@enduml diff --git a/docs/UmlFiles/graph_class_diagram.puml b/docs/UmlFiles/graph_class_diagram.puml new file mode 100644 index 0000000000..d0ee9b1080 --- /dev/null +++ b/docs/UmlFiles/graph_class_diagram.puml @@ -0,0 +1,51 @@ +@startuml +'https://plantuml.com/class-diagram + +class TrigoGraph { + - trigoEqn: String + - amplitude: double + - frequency: double + - phase: double + - verticalShift: double + - trig: String + + TrigoGraph: void(trigoEqn) + + startGraphAnalysis: void() + + getGraphDetails: void(analyser) + + printGraphDetails: void() +} +class TrigoGraphAnalyser { + - trigoEqn: String + - amplitude: double + - freq: double + - phase: double + - verticalShift: double + - trig: String + + canStartAnalyser: boolean() +} +class TrigoGraphVisualiser { + - amplitude: double + - freqInHz: double + - phase: double + - verticalShift: double + - trig: String + + startVisualiser: void() + # paintComponent: void(g) +} +class Ui { + + printIncorrectFormatEntered: void() + + printAmplitude: void(amplitude: double) + + printFrequency: void(frequency: double) +} +class JFrame +abstract Graphics + + + + +TrigoGraph ..> Ui +TrigoGraph --> "visualiser 0..1"TrigoGraphVisualiser +TrigoGraph --> "analyser 0..1"TrigoGraphAnalyser +TrigoGraphVisualiser --> JFrame +TrigoGraphVisualiser ..> Graphics + +@enduml \ No newline at end of file diff --git a/docs/UmlFiles/invalid_file_handler_sequence_diagram.puml b/docs/UmlFiles/invalid_file_handler_sequence_diagram.puml new file mode 100644 index 0000000000..5ee2091c81 --- /dev/null +++ b/docs/UmlFiles/invalid_file_handler_sequence_diagram.puml @@ -0,0 +1,33 @@ +@startuml +'https://plantuml.com/sequence-diagram + + --> ":InvalidNotesFileHandler": responseHandler(path, notes) + activate ":InvalidNotesFileHandler" + ":InvalidNotesFileHandler" -> ":Scanner": Scanner() + activate ":Scanner" + ":Scanner" -> ":Scanner": nextLine() + alt userInput is "y" + ":InvalidNotesFileHandler" -> ":PrintWriter": PrintWriter(path) + activate ":PrintWriter" + ":PrintWriter" -> ":PrintWriter": print("") + ":PrintWriter" -> ":PrintWriter": close() + ":PrintWriter" --> ":InvalidNotesFileHandler" + deactivate ":PrintWriter" + ":InvalidNotesFileHandler" -> ":ArrayList": clear() + activate ":ArrayList" + ":ArrayList" --> ":InvalidNotesFileHandler" + deactivate ":ArrayList" + else userInput is "n" + ":InvalidNotesFileHandler" -> ":Timer": Timer() + activate ":Timer" + ":InvalidNotesFileHandler" -> ":TimerTask": TimerTask() + activate ":TimerTask" + ":InvalidNotesFileHandler" -> ":Timer": schedule(TimerTask, delay) + ":Timer" -> ":TimerTask": run() + ":TimerTask" -> :exit(0) + deactivate ":Timer" + deactivate ":TimerTask" + end + deactivate ":Scanner" + deactivate ":InvalidNotesFileHandler" +@enduml \ No newline at end of file diff --git a/docs/UmlFiles/load_sequence_diagram.puml b/docs/UmlFiles/load_sequence_diagram.puml new file mode 100644 index 0000000000..b6c92c2366 --- /dev/null +++ b/docs/UmlFiles/load_sequence_diagram.puml @@ -0,0 +1,66 @@ +@startuml +activate System + +--> ":NotesFileParser": loadFile(path) +activate ":NotesFileParser" +":NotesFileParser" -> ":ArrayList": ArrayList() +activate ":ArrayList" +":ArrayList" --> ":NotesFileParser" +deactivate ":ArrayList" +":NotesFileParser" -> ":Scanner": Scanner(path) +activate ":Scanner" +":NotesFileParser" -> ":Scanner": scanner.hasNextLine() +loop for each line + ":Scanner" -> ":Scanner": scanner.nextLine() + ":NotesFileParser" -> ":NoteParser": parseNoteString(noteScanner) + activate ":NoteParser" + ":NoteParser" -> ":String": split() + activate ":String" + ":String" --> ":NoteParser" + deactivate ":String" + alt noteInfo.length == 4 + ":NoteParser" -> ":Note": Note() + activate ":Note" + ":Note" --> ":NoteParser" + deactivate ":Note" + ":NoteParser" --> ":NotesFileParser": note + ":NotesFileParser" -> ":ArrayList": add() + activate ":ArrayList" + ":ArrayList" --> ":NotesFileParser" + deactivate ":ArrayList" + else noteInfo.length != 4 + ":NoteParser" -> ":InvalidFormatException": throw exception + activate ":InvalidFormatException" + ":InvalidFormatException" --> ":NoteParser" + deactivate ":InvalidFormatException" + end +end +deactivate ":NoteParser" +deactivate ":Scanner" + +alt file is invalid + ":NotesFileParser" -> ":InvalidNotesFileHandler": responseHandler(path, notes) + activate ":InvalidNotesFileHandler" + alt userInput is "y" + ":InvalidNotesFileHandler" -> ":PrintWriter": PrintWriter(path) + activate ":PrintWriter" + ":PrintWriter" --> ":InvalidNotesFileHandler" + deactivate ":PrintWriter" + ":InvalidNotesFileHandler" -> ":ArrayList": clear() + activate ":ArrayList" + ":ArrayList" --> ":InvalidNotesFileHandler" + deactivate ":ArrayList" + else userInput is "n" + ":InvalidNotesFileHandler" -> System: exit(0) + deactivate ":InvalidNotesFileHandler" + end +else file is valid + <-- ":NotesFileParser": notes +end + +deactivate ":NotesFileParser" + +deactivate System + +@enduml + diff --git a/docs/UmlFiles/note_parser_sequence_diagram.puml b/docs/UmlFiles/note_parser_sequence_diagram.puml new file mode 100644 index 0000000000..3097d8f1ee --- /dev/null +++ b/docs/UmlFiles/note_parser_sequence_diagram.puml @@ -0,0 +1,59 @@ +@startuml + --> ":NoteParser": parseNoteString(noteScanner) + activate ":NoteParser" + ":NoteParser" -> ":String": split() + activate ":String" + ":String" --> ":NoteParser" + deactivate ":String" + alt noteInfo.length == 4 + alt priorityStr is valid + ":NoteParser" -> ":NotePriority": Priority.valueOf(priorityStr) + activate ":NotePriority" + ":NotePriority" --> ":NoteParser" + deactivate ":NotePriority" + else priorityStr is invalid + ":NoteParser" -> ":InvalidFormatException": throw exception + activate ":InvalidFormatException" + ":InvalidFormatException" --> ":NoteParser" + deactivate ":InvalidFormatException" + end + alt isDoneStr is valid + ":NoteParser" -> ":String": equals() + activate ":String" + ":String" --> ":NoteParser" + deactivate ":String" + else isDoneStr is invalid + ":NoteParser" -> ":InvalidFormatException": throw exception + activate ":InvalidFormatException" + ":InvalidFormatException" --> ":NoteParser" + deactivate ":InvalidFormatException" + end + alt reviewCountStr is valid + ":NoteParser" -> ":Integer": parseInt(reviewCountStr) + activate ":Integer" + ":Integer" --> ":NoteParser" + deactivate ":Integer" + else reviewCountStr is invalid + ":NoteParser" -> ":InvalidFormatException": throw exception + activate ":InvalidFormatException" + ":InvalidFormatException" --> ":NoteParser" + deactivate ":InvalidFormatException" + end + ":NoteParser" -> ":Note": Note(noteStr, priority) + activate ":Note" + ":Note" -> ":Note": setReviewCount(reviewCount) + alt isDone = true + ":Note" -> ":Note": markAsDone() + else isDone = false + ":Note" -> ":Note": markAsNotDone() + end + ":Note" --> ":NoteParser" + deactivate ":Note" + <-- ":NoteParser": note + else noteInfo.length != 4 + ":NoteParser" -> ":InvalidFormatException": throw exception + activate ":InvalidFormatException" + ":InvalidFormatException" --> ":NoteParser" + deactivate ":InvalidFormatException" + end +@enduml \ No newline at end of file diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abd9fbe891..6745fc2a7f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,42 +1,773 @@ -# User Guide +# GitHub User Guide for BadMaths ➕➖✖️➗ -## Introduction +## Table of Contents: -{Give a product intro} + + * [Introduction 🧮](#introduction-) + * [Quick Start](#quick-start) + * [Features](#features) + * [1) Graph Analyser and Visualiser: `Graph`](#1-graph-analyser-and-visualiser-graph) + * [2) Matrix Calculation: `Matrix`](#2-matrix-calculation-matrix) + * [3) Store Notes: `Store`](#3-store-notes-store) + * [4) Display All Notes: `List`](#4-display-all-notes-list) + * [5) Display A Specific Note: `List `](#5-display-a-specific-note-list-index) + * [6) Delete Notes: `Delete `](#6-delete-notes-delete-index) + * [7) Clear All Notes Stored In Notes List `Clear`](#7-clear-all-notes-stored-in-notes-list-clear) + * [8) Mark Notes: `Mark`](#8-mark-notes-mark) + * [9) Unmark Notes: `Unmark`](#9-unmark-notes-unmark) + * [10) List All Items Marked As Completed: `FindMark`](#10-list-all-items-marked-as-completed-findmark) + * [11) List All Notes That Are Not Marked As Completed: `FindUnmark`](#11-list-all-notes-that-are-not-marked-as-completed-findunmark) + * [12) Find Notes Using Keyword: `FindInfo`](#12-find-notes-using-keyword-findinfo) + * [13) Prioritize A Note](#13-prioritize-a-note) + * [14) Display All Notes Based On All Priority Types: `Rank Priority`](#14-display-all-notes-based-on-all-priority-types-rank-priority) + * [15) Display All Notes Based On Review Count: `Rank Review Count`](#15-display-all-notes-based-on-review-count-rank-review-count) + * [16) Display All Notes Of A Certain Priority Type: `FindPrior`](#16-display-all-notes-of-a-certain-priority-type-findprior) + * [17) Solving Quadratic Equations: `Quadratic`](#17-solving-quadratic-equations-quadratic) + * [18) Command History `History`](#18-command-history-history) + * [19) Help Manual `Help`](#19-help-manual-help) + * [20) Exit BadMaths `Bye`](#20-exit-badmaths-bye) + * [FAQ](#faq) + * [Command Summary](#command-summary) + * [General](#general) + * [Notes](#notes) + * [Graph](#graph) + * [Quadratic](#quadratic) + + +## Introduction 🧮 + +Hello! Welcome to BadMaths! BadMaths is an integrated study tool that performs Mathematical Operations and contains +various features for note-taking. + +To help you get started, our team has put together this user guide to guide you on +the steps to operate BadMaths for your study woes. ## Quick Start -{Give steps to get started quickly} +Before you start using BadMaths, make sure you have the following ready! 1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). +2. Down the latest version of `BadMaths` from [here](https://github.com/AY2223S2-CS2113-F10-2/tp/releases). + +## Features + +### 1) Graph Analyser and Visualiser: `Graph` +This feature accepts a trigonometry equation (Sinusoidal signal) and outputs the amplitude, frequency, phase, and vertical shift. +It also displays the image of the corresponding graph. + +Format: `Graph [Amplitude]*[Trigo]([Frequency]*x[sign][PhaseShift])[sign][VerticalShift]` + +* `Amplitude` can be any positive number. E.g. `15.5`, `4`, `0` +* `Trigo` can be sin, cos or tan. +* `Frequency` can be any positive number (more than 0). E.g. `100` + * When entering frequency, one can include 𝜋 by typing `2*pi*x` instead of `6.283*x` +* `PhaseShift`, `VerticalShift` can be any positive number. E.g. `15.1`, `4`, `0`,`1` +* `sign` can be + or - . +* `[` and `]` are not needed when entering the input. +* Some form of elimination is possible: + * When `Amplitude` is 1, `1*cos(1*x)` can be shortened to `cos(1*x)` + * When `PhaseShift` or `verticalShift` is 0, `[sign][PhaseShift]` or `[sign][VerticalShift]` are not needed. + +**Note: Accuracy of graph drawn is up to 4 digits (Thousand place) for numerical inputs. E.g. `9999`.** + + +Example input 1: +``` +Graph 2985*sin(5999*x+2665)-8678 +``` +Example output 1: +``` +This is the amplitude: 2985.0 +This is the freq (Hz): 954.7705036082801 +This is the phase: 2665.0 +This is the vertical shift: -8678.0 +``` +![img_4.png](ImagesForUserGuide/Graph_eg_output_1.png) + +Example input 2: +``` +Graph 2*sin(5*pi*x-2)+5.6 +``` +Example output 2: +``` +This is the amplitude: 2.0 +This is the freq (Hz): 2.5 +This is the phase: -2.0 +This is the vertical shift: 5.6 +``` +![img_5.png](ImagesForUserGuide/Graph_eg_output_2.png) + +Example input 3: +``` +Graph cos(5*x) +``` +Example output 3: +``` +This is the amplitude: 1.0 +This is the freq (Hz): 0.7957747154594768 +This is the phase: 0.0 +This is the vertical shift: 0.0 +``` +![img_6.png](ImagesForUserGuide/Graph_eg_output_3.png) + +### 2) Matrix Calculation: `Matrix` +This feature accepts matrix equation and outputs calculation result. + +Format: `Matrix [Matrix] [operator] [Matrix]` + +* `[Matrix]` is the 2 dimensional matrix with integer elements. When you declare the matrix, you should follow the matrix format below: + ``` + [1,2;3,4] + ``` + * You should separate the elements with comma (,) in the single row. + * You should separate the rows with the semicolons. + + ``` + [1,2;3,4].T + ``` + * You can declare transposed matrix with the transpose annotation `.T`. + * Transposed matrix above is equal with matrix `[1,3;2,4]`. + + > NOTE : The entities of matrix should be all integer. + + > NOTE : The length of every rows in matrix should be the same with each other. + +* `[operator]` is the matrix operator. You can use 4 operators below: + * `.*` : matrix multiplication + * `*` : element wise product + * `+` : matrix addition + * `-` : matrix subtraction + + > NOTE : Shape of the two operands should be properly matched with each other for the given operator. + > For the `.*` operator, the number of the columns of operand1 should be the same with the number of the rows of operand2. + > For the `*`, `+`, and `-` operators, the shape of the two operands should be identical. + +#### You can see the right examples of the matrx calculation below: +* Examples for the matrix multiplication + + *Input* : + ``` + Matrix [1,2;3,4] .* [4,5;6,7] + ``` + + *Output* : + ``` + Result. + 1. shape : 2 x 2 + 2. value : + 0) 16 19 + 1) 36 43 + ``` +* Examples for the matrix multiplication with transpose + + *Input* : + ``` + Matrix [1,2;3,4] .* [4,5;6,7].T + ``` + + *Output* : + ``` + Result. + 1. shape : 2 x 2 + 2. value : + 0) 14 20 + 1) 32 46 + ``` +* Examples for the matrix element wise product + + *Input* : + ``` + Matrix [1,2;3,4] * [4,5;6,7] + ``` + + *Output* : + ``` + Result. + 1. shape : 2 x 2 + 2. value : + 0) 4 10 + 1) 18 28 + ``` +* Examples for the matrix addition + + *Input* : + ``` + Matrix [1,2;3,4] + [4,5;6,7] + ``` + + *Output* : + ``` + Result. + 1. shape : 2 x 2 + 2. value : + 0) 5 7 + 1) 9 11 + ``` +* Examples for the matrix subtraction + + *Input* : + ``` + Matrix [1,2;3,4] - [4,5;6,7] + ``` + + *Output* : + ``` + Result. + 1. shape : 2 x 2 + 2. value : + 0) -3 -3 + 1) -3 -3 + ``` + +#### You can see the examples for common mistakes below: +* Every entities of the matrix should be integer. + + *Input* : + ``` + Matrix [1,2;3,4] .* [4,5;6,a] + ``` + ``` + Matrix [1,2;3,4] .* [4,5;6,7.1] + ``` + + *Output* : + ``` + + Every entities of matrix should be integer. + ``` + +* Length of every rows should be the same with each other. + + *Input* : + ``` + Matrix [1,2;3,4,5] * [4,5;6,7] + ``` + + *Output* : + ``` + + Length of every rows should be the same with each other. + ``` + +* There is shape mismatch between t1 and t2 : cannot execute matrix calculation. + + *Input* : + ``` + Matrix [1,2;3,4] .* [1,2,3;3,4,5] + ``` + ``` + Matrix [1,2;3,4] + [1,2,3;3,4,5] + ``` + + *Output* : + ``` + + There is shape mismatch between t1 and t2 : cannot execute matrix calculation. + ``` + +### 3) Store Notes: `Store` +* Adds a new item to the Notes list. +* Format: `Store ` + +Example input: +``` +Store isNote +``` +Expected output: +``` +You have added this note: +isNote +Now you have of notes in the list +``` + +### 4) Display All Notes: `List` +* Display a list of all items stored by user. +* Format: `List` + +Example input: +``` +List +``` +Expected output: +``` +Here are the notes you have stored: +1. [LOW][N][0]note_item_1 +2. [LOW][N][0]note_item_2 +3. [LOW][N][0]note_item_3 +``` + +### 5) Display A Specific Note: `List ` +* Display a particular item in the Notes list through index of list item. +* Format: `List ` + +Example input: +``` +List 2 +``` +Expected output: +``` +Here is the note you are looking for +2. [LOW][N][0]note_item_2 +``` + +### 6) Delete Notes: `Delete ` +* Delete a particular item stored in the Notes list through index of list item. +* Format: `Delete. ` + +Example input: +``` +Delete 2 +``` +Expected output: +``` +You have removed this note: +[LOW][N][0]note_item_2 +Now you have notes in the list. +``` + +### 7) Clear All Notes Stored In Notes List `Clear` +* Delete all note items stored in Notes List. +* Format: `Clear` + +Example input: +``` +Clear +``` +Expected output: +``` +File content cleared successfully! +``` +### 8) Mark Notes: `Mark` +* Mark a particular item in Notes List as completed. +* The mark bracket will change from `[N]` to `[Y]`. +* Format: `Mark ` -## Features +Example input: +``` +Mark 2 +``` +Expected output: +``` +You have marked this note as done: +[LOW][Y][0]note_item_2 +``` +### 9) Unmark Notes: `Unmark` +* Unmark a particular item in Notes List as incomplete. +* The mark bracket will change from `[Y]` to `[N]`. -{Give detailed description of each feature} +* Format: `Unmark ` -### Adding a todo: `todo` -Adds a new item to the list of todo items. +Example input: +``` +Unmark 2 +``` +Expected output: +``` +You have unmarked this note: +[LOW][N][0]note_item_2 +``` +### 10) List All Items Marked As Completed: `FindMark` +* Display a list of all note items marked as completed. +* All items with mark bracket `[Y]` will be displayed. +* Format: `FindMark` -Format: `todo n/TODO_NAME d/DEADLINE` +Example input: +``` +FindMark +``` +Expected output: +``` +Here are the notes you are searching for: +1. [LOW][Y][0]note_item_1 +2. [LOW][Y][0]note_item_3 +``` -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. +### 11) List All Notes That Are Not Marked As Completed: `FindUnmark` +* Display a list of all incomplete note items. +* All items with mark bracket `[N]` will be displayed. +* Format: `FindUnmark` + +Example input: +``` +FindUnmark +``` +Expected output: +``` +Here are the notes you are searching for: +1. [LOW][N][0]note_item_2 +``` + +### 12) Find Notes Using Keyword: `FindInfo` +* Find items stored in Notes by searching for a keyword. +* Format: `FindInfo ` + +Assuming that the List is as follows: +``` +1. [LOW][N][0]Add +2. [LOW][N][0]Subtract +3. [LOW][N][0]Multiply +``` +Example input: +``` +FindInfo Add +``` +Expected output: +``` +Here are the notes you are searching for: +1. [LOW][N][0]Add +``` + +### 13) Prioritize A Note +Change the priority of a certain note in the notes list. + +Format: ` ` +Example of usage: `High 1` + +* The `` must be one of the three: `High`, `Medium`, `Low`. + +Example of usage: + +`High 1` + +Expected outcome: + +```` +You have changed its priority to HIGH +1: [HIGH][N][0]Note 1 +```` +Example of usage: + +`Medium 3` + +Expected outcome: + +```` +You have changed its priority to MEDIUM +3: [MEDIUM][N][0]Note 3 +```` + +### 14) Display All Notes Based On All Priority Types: `Rank Priority` +Display all items stored in the Notes List based on the respective priority rankings. + +Format: `Rank Priority` Example of usage: -`todo n/Write the rest of the User Guide d/next week` +`Rank Priority` + +Expected outcome: +```` +High priority notes: +[HIGH][N][0]note_item_1 +Medium priority notes: +[MEDIUM][N][0]note_item_2 +Low priority notes: +[LOW][N][0]note_item_3 +```` + +### 15) Display All Notes Based On Review Count: `Rank Review Count` +Display all items stored in the Notes List based on the respective review count rankings. + +Format: `Rank Review Count` + +Example of usage: + +`Rank Priority` + +Expected outcome: + +```` +Notes sorted by review count: +note_item_1 (review count: 3) +note_item_2 (review count: 2) +note_item_3 (review count: 1) +```` + +### 16) Display All Notes Of A Certain Priority Type: `FindPrior` +* Find all notes stored in the list based on the priority that users are searching for. +* Format: `FindPrior ` +* The `` must be one of the three types: `High`, `Medium`, `Low`, case-insensitive. + + +Example input: +``` +FindPrior LOW +``` +Expected outcome: +```` +Here are the notes you are searching for: +1. [LOW][N][0]note_item_1 +2. [LOW][N][0]note_item_2 +3. [LOW][N][0]note_item_3 +```` -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` +Example input: +``` +FindPrior mEdIuM +``` +Expected outcome: +```` +Here are the notes you are searching for: +1. [MEDIUM][N][0]note_item_4 +2. [MEDIUM][N][0]note_item_5 +```` + +### 17) Solving Quadratic Equations: `Quadratic` +Solves for `x` in a quadratic equation. + +Format: `Quadratic [quadratic equation]` + +- `Quadratic` must be in this exact format (With uppercase Q) +- The quadratic equation must look like this: `2x^2 + 2x + 1` with spaces between each value. Both double and integer + numbers are acceptable (eg. `-2.5x^2 + 3 + 1`). Inputting just the sign is also acceptable (eg. `-x^2 + x - 1`). + +Examples: + +- Input: +```` +Quadratic 2x^2 + 2x + 1 +```` +- Output: +```` +x is imaginary. +```` +- Input: +```` +Quadratic x^2 + 4x - 5 +```` +- Output: +```` +x1 = 1.0 , x2 = -5.0 +There is a minimum point: (-2.0, -9.0) +```` +- Input: +```` +Quadratic x^2 + 3 +```` +- Output: +```` +Please use the format as shown below: +ax^2 + bx + c +```` + +### 18) Command History `History` +* Display a list of Command History that users have + entered during the current programme run session. +* Format: History + +Assuming that user have input `Store index` after starting badMaths: + +Example input: +``` +History +``` +Expected output: +``` +Here are the list of commands that you have entered so far: +Store index +History +``` + +### 19) Help Manual `Help` +* Display the content of Help Manual for BadMaths. +* Format: `Help` + +Example input: +``` +Help +``` +Expected output: +``` +------------------------------------------------------------------ +Hello! Welcome to the Help Manual for BadMaths! +------------------------------------------------------------------ +1. Type -> Graph [equation] <- to perform graph calculations +2. Type -> Matrix [equation] <- to perform matrix calculations +3. Type -> Store [any_string] <- to add notes +4. Type -> List <- to list all stored notes +5. Type -> List [index] <- to display a particular note +6. Type -> Delete [index] <- to delete a particular note +7. Type -> Clear <- to delete all stored notes +8. Type -> Mark [index] <- to mark a particular note as completed +9. Type -> Unmark [index] <- to unmark a particular note as incomplete +10. Type -> FindMark <- to display a list of all notes marked as completed +11. Type -> FindUnmark <- to display a list of all notes marked as incomplete +12. Type -> FindInfo <- to find items stored in Notes through searching for a keyword +13. Type -> [Priority] [index] <- to change the priority of a note +14. Type -> Rank Priority <- to display all notes of all priority rankings +15. Type -> Rank Review Count <- to display all notes ranked by review count +16. Type -> FindPrior [Priority] <- to display all notes of a certain priority +17. Type -> Quadratic [equation] <- to perform quadratic calculations +18. Type -> History <- to display a list of command history +19. Type -> Help <- to display content of Help Manual +20. Type -> Bye <- to exit program + +------------------------------------------------------------------- +Thank you for using BadMaths. We hope that BadMaths will be a useful study tool +in helping you to perform Mathematical Operations. +For more details, please visit our GitHub website [https://github.com/AY2223S2-CS2113-F10-2/tp]. +If you have any queries on BadMaths, please contact [wilsonleejunwei@u.nus.edu]. +------------------------------------------------------------------- +``` + +### 20) Exit BadMaths `Bye` +* Exit and leave BadMaths: +* Format: `Bye` + +Example input: +``` +Bye +``` +Expected outcome: +```` +Goodbye! +```` ## FAQ -**Q**: How do I transfer my data to another computer? +**Q1**: How do I start and run BadMaths? + +**A1**: + +- Download the latest release of BadMaths [here](https://github.com/AY2223S2-CS2113-F10-2/tp/releases). +- Save the java file to a new folder. +- Open command prompt by typing `cmd` in the Windows search bar. +- Navigate to the folder via `cd "folder path"`. (eg. `cd C:\Users\your_name\Desktop\BadMaths`). +- Type `java -jar BadMaths.jar` to run BadMaths. +- Follow the `User Guide` to begin testing. + +**Q2**: How do I exit and leave BadMaths? + +**A2**: You can terminate the MathHelp programme by simply typing +`Bye` in the command. + +**Q3**: What should I do if the file is corrupted? + +**A3**: + +- When BadMaths detects that the target file is corrupted, BadMaths will request whether you want to clear the file for +continual use by print the prompt message +```` +Sorry, your notes file seems to be corrupted :( +Do you want to reset the file? (y/n) +```` +- You can inform BadMaths whether you want to clear the file by typing `y` or `n`. +- By typing `n` not to empty the file, BadMaths will prompt you for your choice and automatically exit after +`10 seconds`. In such cases, please correct the file format manually before continuing to use BadMaths. +- By typing `y` to empty the file, BadMaths will prompt you when the target file is successfully emptied, +and you will be able to continue using BadMaths by then. + +**Q4**: In the matrix calculation, can I declare matrix with 3D dimension or above? + +**A4**: No. Badmaths only supports 2D matrix in the calculation. + +**Q5**: In the matrix calculation, can I declare 1D matrix? + +**A5**: No. Badmaths only supports 2D matrix in the calculation. But you can treat 2D matrix with the single row as 1D matrix. +If you declare matrix like `[1, 2, 3]`, the program would recognize it as 2D matrix with shape of `1 * 3`. + +**Q6**: In the matrix calculation, can I use multiple operators in single expression like `Matrix [1,2;3,4] + [1,2;3,4] + [1,2;3,4]`? -**A**: {your answer here} +**A6**: No. Only single operator should be contained in the single expression with two operands. ## Command Summary -{Give a 'cheat sheet' of commands here} +### General +``` +History +``` +``` +Help +``` +``` +Bye +``` +### Notes +``` +Store isNote +``` +``` +List +``` +``` +List 2 +``` +``` +Delete 2 +``` +``` +Clear +``` +``` +Mark 2 +``` +``` +Unmark 2 +``` +``` +FindMark +``` +``` +FindUnmark +``` +``` +FindInfo Add +``` +``` +High 1 +``` +``` +Medium 1 +``` +``` +Low 1 +``` +``` +Rank Priority +``` +``` +Rank Review Count +``` +``` +FindPrior HIGH +``` +``` +FindPrior MEDIUM +``` +``` +FindPrior LOW +``` +### Graph + ``` + Graph 2*tan(2*pi*x+5) + ``` + ``` + Graph sin(1*x) + ``` + ``` + Graph 2*cos(1*x-6)-100 + ``` +### Quadratic +```` +Quadratic 2x^2 + x - 5 +```` +```` +Quadratic -x^2 - x + 2.5 +```` -* Add todo `todo n/TODO_NAME d/DEADLINE` +### Matrix +``` +Matrix [1,2;3,4] .* [1,2;3,4] +``` +``` +Matrix [1,2;3,4] .* [1,2;3,4].T +``` +``` +Matrix [1,2;3,4] * [1,2;3,4] +``` +``` +Matrix [1,2;3,4] + [1,2;3,4] +``` +``` +Matrix [1,2;3,4] - [1,2;3,4] +``` diff --git a/docs/team/0nandon.md b/docs/team/0nandon.md new file mode 100644 index 0000000000..6e4c1ccea5 --- /dev/null +++ b/docs/team/0nandon.md @@ -0,0 +1,61 @@ +# 🧑🏻‍💻 Seungjun Lee, Project Portfolio Page + +## 🤖 Project BadMaths + +BadMaths is a study tool focusing on mathematical help and note-taking. It supports +a number of mathematical functions, including trigonemetric graphs, quadratic equations, and matrix calculations. + +## 👊🏻 Summary of Contributions + +### Code contributed + +My code contribution can be mainly separated with two parts: + + * Source code for the matrix calculation and possible exceptions + * JUnit test codes for the matrix calculation + +If you want to see my code contributions more specifically, click [[here]](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=0nandon&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByAuthors&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=0nandon&tabRepo=AY2223S2-CS2113-F10-2%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false). + +### Features added + +- Added a feature to support various matrix calculation. This allows users to input matrix equation and BadMaths + would be able to output the answer. BadMaths supports four operations below: + + 1. Matrix multiplication + 2. Matrix element wise product + 3. Matrix addition + 4. Matrix subtraction + 5. Matrix transpose + +### Enhancements added + +- Added JUnit tests for the `Calculate`, `Parser`, `Execute` classes. +- Improve code more defensive with handling various possible exceptions: +- Refined the code to be more OOP with following [[code standard]](https://se-education.org/guides/conventions/java/basic.html). +- Added comments with `JavaDoc` style for the readability. +- Added `logging`, `assert` statement for making debugging more easily. + +### Contributions to the UG + +- Contributed the section explaining the usage of the Matrix calculation. +- Added various examples for the matrix calculation and expected output. +- Added various examples for common mistakes that users can possibly do. +- Added several cautions for the appropriate usage of the matrix calculation. +- Added `FAQ` for the matrix calculation. +- Added `Command Summary` for the matrix calculation. +- Refined the whole contents of the UG for the readability. + +### Contributions to the DG + +- Contributed to the section detailing the functionality of the matrix calculation. +- Created a `sequence diagram` to further explain how matrix calculation is conducted. +- Created a `class diagram` to further explain relationships between classes for the matrix part. +- Refined the whole contents of the DG for the readability. + +### Contributions to team-based tasks + +- Contributed to brainstorming of ideas and feature generation. +- Tracked v1.0, v2.0, v2.1 milestones. +- Provided basic coding advice and code quality checking assistance to group members. +- Reviewed Pull Requests with assistance before merging them into the master branch on Github. +- Manually tested jar file with checking whether there is any error. diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md deleted file mode 100644 index ab75b391b8..0000000000 --- a/docs/team/johndoe.md +++ /dev/null @@ -1,6 +0,0 @@ -# John Doe - Project Portfolio Page - -## Overview - - -### Summary of Contributions diff --git a/docs/team/khooyourun.md b/docs/team/khooyourun.md new file mode 100644 index 0000000000..8485f3be89 --- /dev/null +++ b/docs/team/khooyourun.md @@ -0,0 +1,51 @@ +# Khoo You Run - Project Portfolio Page + +## Project BadMaths + +BadMaths is a study tool focusing on mathematical help and note-taking. Provides features to aid in solving questions +revolving around matrices, quadratic equations, and trigonometric graphs. + +## Summary of Contributions + +### Code contributed +[Here are my code contributions](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=khooyourun&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other&tabOpen=true&tabType=authorship&tabAuthor=khooyourun&tabRepo=AY2223S2-CS2113-F10-2%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) + +### General functionalities implemented + +- Created and implemented the initial `BadMaths` class, `Command` class and `Parser` class that helped to facilitate the general +flow of the program. BadMaths class took in user input, Parser class made sense of the user input and Command class executed +the desired features. All the included features in BadMaths depend and run on these 3 classes. + +### Features added + +- Added a feature to solve quadratic equations. This allows users to input any quadratic equation and BadMaths would be +able to output the answer. If the answer is imaginary, BadMaths would tell the user as such. BadMaths would also find the +minimum or maximum point of the quadratic graph. + +### Enhancements added + +- Added JUnit Tests to `Quadratic`, `QuadraticParser` and `Parser`. +- Made the code more OOP and improved readability. +- Enhanced code defence by protecting it against bugs and possible exceptions. + +### Contributions to the UG + +- Contributed the Table of Contents for easy access to various sections of the UG. +- Contributed the section explaining the usage of the Quadratic solver feature. +- Contributed to the FAQ section. + +### Contributions to the DG + +- Created the Architecture Diagram. +- Contributed to the section detailing the handling of User Input. +- Contributed to the section detailing the functionality of the Quadratic solver. +- Created a sequence diagram to further explain how Quadratic Solver works. +- Added User Stories. +- Added instructions for manual testing. + +### Contributions to team-based tasks / Review contributions + +- Contributed to brainstorming of ideas and feature generation. +- Tracked v1.0, v2.0 milestones. +- Helped group members with code quality checking and general coding advice. +- Helped to review Pull Requests before merging into master branch on Github. diff --git a/docs/team/wilsonlee2000.md b/docs/team/wilsonlee2000.md new file mode 100644 index 0000000000..ddef350237 --- /dev/null +++ b/docs/team/wilsonlee2000.md @@ -0,0 +1,54 @@ +# Wilson Lee Jun Wei (Project Portfolio Page) + +## About Me +Hello there! +I am a second year student studying Computer Engineering, with a minor in Interactive Media Development at the National University Of Singapore. +If you have any enquiries, feel free to reach out to me at wilsonleejunwei@u.nus.edu + +## Product Overview - BadMaths +BadMaths is a Mathematical Study Tool that aims to help users to perform Mathematical Operations +effectively and efficiently and contains various functionalities for note-taking + +## Summary of Contributions +### 1) Code Contributed: +Click [here](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=WilsonLee&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByAuthors&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&zFR=false&tabAuthor=WilsonLee2000&tabRepo=AY2223S2-CS2113-F10-2%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) +to view my codes contributed for this project + +### 2) Enhancements Implemented: +* Added `Store` Feature for notes taking +* Added `List` Feature for displaying items stored in notes +* Added `Delete` Feature for removing items stored in notes +* Added `History` Feature for displaying a list of all commands input by users +* Refactoring codes as classes for `Store`, `List`, `Delete` and `CommandHistory` +* Implemented JUnit Tests for `Store`, `List`, `Delete` and `CommandHistory` +* Added details and improvements towards `HelpManual.txt` +* Improve codes to more OOP + +### 3) UserGuide Contributions: +* Contributed to overall formatting of UserGuide +* Contributed to documentation for `Store`, `List`, `Delete`, `Clear`, `Mark`, `Unmark`, +`FindMark`, `FindUnmark`, `FindInfo`, `FindPrior`, `History`, `Help`, `Bye` +* Contributed to Command Summary for `Notes` and `General` + +### 4) DeveloperGuide Contributions: +* Added Introduction +* Added Table of Contents +* Added Sequence Diagram for `Store` +* Added Design & implementation details for `Store` class +* Added Design & implementation details for `Delete` class +* Added Design & implementation details for `Command` class +* Added Design & implementation details for `List` class +* Added Design & implementation details for `CommandHistory` class +* Added Design & implementation details for `Ui` class +* Added Design & implementation details for `notes.txt` file + +### 5) Contributions to team-based tasks: +* Tracked `v1.0`, `v2.0`, and `v2.1` milestones +* Assist in reviewing and approving team members' Pull Requests before merging to team's master branch +* Contributed to team's brainstorming and discussion of ideas and features for BadMaths +* Management of issues created on GitHub +* Contributed to team's Google documents and Google sheet for BadMaths implementation +* Helped team members in understanding GitHub properties such as `push` and `pull` + +### 6) Review / Mentoring Contributions: +* Link to PRs reviewed [here](https://github.com/AY2223S2-CS2113-F10-2/tp/pulls?q=is%3Apr+reviewed-by%3AWilsonLee2000) diff --git a/docs/team/yc-michael.md b/docs/team/yc-michael.md new file mode 100644 index 0000000000..b422b05496 --- /dev/null +++ b/docs/team/yc-michael.md @@ -0,0 +1,36 @@ +# Hui Yu Cong - project Portfolio Page + +## Overview of product: BadMaths + +BadMaths is an integrated study tool that performs Mathematical Operations and contains +various features for note-taking. + +## Summary of Contributions + +### Code contributed +[My code contributions](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=YC-Michael&tabRepo=AY2223S2-CS2113-F10-2%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) + +### Enhancements implemented + +- Created the Ui class to print outputs to the user +- Added a feature that analyses basic trigonometry signals +- Enhance the stated feature by visualising it using JFrame +- Make the code more OOP and bug free +- Added JUnit tests for TrigoGraph, TrigoGraphAnalyser and TrigoGraphVisualiser + +### Contributions to the UG + +- Contributed to `Feature 1: Graph Analyser and Visualiser` +- Contributed to Graph portion of `Command Summary` + +### Contributions to the DG + +- Contributed to `Graph` +- Added UML diagrams for `TrigoGraph class` + +### Contributions to team-based tasks / Review contributions + +- Created team organisation and tracked the progress of milestones v1.0, v2.0 and v2.1 +- Provided ideas for extra features (Review Count to track the number of times a user has viewed that particular note) +- Assisted members in debugging their code offline +- [PRs reviewed](https://github.com/AY2223S2-CS2113-F10-2/tp/pulls?q=is%3Apr+reviewed-by%3AYC-Michael) diff --git a/docs/team/ziqiuzeng.md b/docs/team/ziqiuzeng.md new file mode 100644 index 0000000000..cfb944b174 --- /dev/null +++ b/docs/team/ziqiuzeng.md @@ -0,0 +1,46 @@ +# ZENG ZIQIU's Project Portfolio Page +## Project: BadMaths +BadMaths is an integrated study tool that performs Mathematical Operations and contains various features for note-taking. +## Summary of Contribution +Given below are my contributions to the project: +- Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=ziqiuzeng&breakdown=true) +- New Features: + - Added the ability to detect file corruption when launching program + - Added `Help` feature to display Help Manual of BadMaths + - Added the ability to modify the priority of notes + - Added the ability to find notes by `keyword`, `priority`, `status` + - Added the ability to `mark`/`unmark` note + - Added the ability to `Rank` all notes by `Priority`/`Review Count` + - Added the ability to `clear` all notes +- Enhancements: + - Added JUnit Test for `NotesFileParser`, `NotesFileWriter`, `NotesFileContentManager`, and `NotesFileCleaner` + - Added JUnit Test for `NoteParser` and `InvalidNotesFileHandler` + - Added JUnit Test for `HelpManual` + - Added JUnit Test for `IndexChecker` and `IntegerChecker` + - Refactor `Storage` class and `executeCommand()` method + - Make the code more OOP +- Project Management + - Managed Release [v2.0](https://github.com/AY2223S2-CS2113-F10-2/tp/releases/tag/v2.0) + - Tracked `v1.0`, `v2.0`, and `v2.1` milestones + - Managed issues via GitHub + - Manage team documentations: +[Group Ideas](https://docs.google.com/document/d/1BfeY-7amQIlLvMt-YgQhyi-jJRB1y6goONhYVx2_tj8/edit), +[User Story](https://docs.google.com/spreadsheets/d/1JSthry8kPJip282RwAYTB0ApbxfOQCNXWcnRzuLhJNI/edit#gid=0), +[Draft UG](https://docs.google.com/document/d/1PGL8eMsa442esYVmjpDL4k8mMSnMI010kLE77_K-1T0/edit) +- Documentation: + - User Guide: + - Added documentation for `Note` features + - Added documentation for the feature `Help` + - Contributed to the `FAQ` section + - Developer's Guide: + - Added format details of the `notes.txt` file + - Added sequence diagram of `NotesFileParser` + - Added implementation details of `Help`, `Storage`, and `Note` +- Community + - [PR reviewed](https://github.com/AY2223S2-CS2113-F10-2/tp/issues?q=reviewed-by%3AZiqiuZeng) + - Contributed to brainstorming of ideas and features + - Provided ideas for `Command History` to keep track of previous commands + - Help teammates with basic feature implementation ideas and general code quality advice + - Help teammates with code testing and debugging + - Reported bugs and suggestions for other team in the class [PED](https://github.com/ZiqiuZeng/ped/issues) + diff --git a/src/main/java/seedu/badmaths/BadMaths.java b/src/main/java/seedu/badmaths/BadMaths.java new file mode 100644 index 0000000000..d8ffa547b8 --- /dev/null +++ b/src/main/java/seedu/badmaths/BadMaths.java @@ -0,0 +1,86 @@ +package seedu.badmaths; + +import seedu.badmaths.note.NotesList; +import seedu.badmaths.storage.NotesFileParser; +import seedu.badmaths.ui.Ui; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import java.util.Arrays; +import java.util.Scanner; +import java.io.File; +import java.io.IOException; + +public class BadMaths { + private static final String path = "data/notes.txt"; + + private static final Set VALID_COMMANDS = new HashSet<>(Arrays.asList( + "Graph", "Bye", "List", "Store", "Matrix", "Help", "FindInfo", "FindPrior", "FindMark", "FindUnmark", "Low", + "Medium", "High", "Delete", "Mark", "Unmark", "Clear", "Rank", "Quadratic", "History" + )); + + /** + * Checks whether command is one of the valid commands + * Throws exception if not + * @param command which is the user inputted command + */ + public static void commandChecker(String command) { + try { + if (!VALID_COMMANDS.contains(command)) { + throw new IllegalArgumentException(); + } + } catch (IllegalArgumentException e) { + Ui.printIncorrectFormatEntered(); + } + } + + public static void notesCreator(String path) { + File notesFile = new File(path); + if (!notesFile.exists()) { + if (!notesFile.getParentFile().exists()) { + notesFile.getParentFile().mkdirs(); + } + try { + notesFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + Command inputCommand = null; + Ui.printWelcomeMessage(); + notesCreator(path); + NotesList notes = new NotesList(NotesFileParser.loadFile(path)); + ArrayList historyCommand = new ArrayList<>(); + CommandHistory commandHist = new CommandHistory(historyCommand); + + while (true) { + Scanner scanner = new Scanner(System.in); + String userInput = scanner.nextLine(); + + Parser parser = new Parser(userInput); + String command = parser.getCommand(); + String toDo = parser.getToDo(); + commandHist.storeCommand(userInput); + + commandChecker(command); + + if (inputCommand == null) { + inputCommand = new Command(command, toDo); + } else { + inputCommand.setCommand(command); + assert inputCommand.getCommand().equals(command) : "inputCommand != command"; + inputCommand.setToDo(toDo); + } + + inputCommand.executeCommand(notes, historyCommand); + if (userInput.equals("Bye")) { + System.exit(0); + } + } + } +} + diff --git a/src/main/java/seedu/badmaths/Command.java b/src/main/java/seedu/badmaths/Command.java new file mode 100644 index 0000000000..993d3ae7d3 --- /dev/null +++ b/src/main/java/seedu/badmaths/Command.java @@ -0,0 +1,174 @@ +/** + * Takes in function and command + * Identifies the function called and executes the appropriate function class + * + * @param command + * @param toDo + */ + +package seedu.badmaths; +import seedu.badmaths.commands.NotesRanker; +import seedu.badmaths.commands.NotesFinder; +import seedu.badmaths.commands.NotesPriorityFinder; +import seedu.badmaths.commands.PrioritySetter; +import seedu.badmaths.commands.NotesMarker; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.storage.NotesFileCleaner; +import seedu.badmaths.trigograph.TrigoGraph; +import seedu.badmaths.ui.Ui; +import seedu.badmaths.matrix.Calculator; +import seedu.badmaths.Quadratic.Quadratic; +import java.util.ArrayList; + + +public class Command { + + private static final String filePath = "data/notes.txt"; + protected String command; + protected String toDo; + ArrayList historyCommand = new ArrayList<>(); + + public Command(String command, String toDo) { + this.command = command; + this.toDo = toDo; + } + + public String getCommand() { + return command; + } + + public void setCommand(String command) { + try { + this.command = command; + } catch (IllegalArgumentException e) { + Ui.printIncorrectFormatEntered(); + } + } + + public void setToDo(String toDo){ + this.toDo = toDo; + } + + public boolean isInvalidTodo(String todo) { + return todo.equals("Invalid todo"); + } + + public void executeCommand(NotesList notes, ArrayList historyCommand) { + TrigoGraph trigoGraph = new TrigoGraph(toDo); + Calculator calculator = new Calculator(); + Quadratic quadratic = new Quadratic(toDo); + CommandHistory commandHist = new CommandHistory(historyCommand); + NotesMarker notesMarker = new NotesMarker(notes, filePath); + PrioritySetter prioritySetter = new PrioritySetter(notes, filePath); + NotesFinder notesFinder = new NotesFinder(notes, filePath); + NotesPriorityFinder notesPriorityFinder = new NotesPriorityFinder(notes, filePath); + NotesRanker notesRanker = new NotesRanker(notes, filePath); + try { + //@@author WilsonLee2000 + assert (command.equals("Bye") || command.equals("Graph") || command.equals("Store") || + command.equals("List") || command.equals("Delete") || command.equals("Mark") || + command.equals("Unmark") || command.equals("Low") || command.equals("Medium") || + command.equals("High") || command.equals("FindInfo") || command.equals("FindPrior") || + command.equals("FindMark") || command.equals("FindUnmark") || command.equals("Rank") || + command.equals("Clear") || command.equals("Help") || command.equals("Matrix") || + command.equals("Quadratic") || command.equals("History")) : "input has incorrect format required"; + //@@author Khooyourun + switch (command) { + case "Bye": + if(!isInvalidTodo(toDo)) { + throw new IllegalTodoException(); + } + System.out.println("Goodbye!"); + break; + case "Graph": + trigoGraph.startGraphAnalysis(); + break; + //@@author WilsonLee2000 + case "Store": + Store store = new Store(notes, toDo); + store.storeNotes(); + break; + //@@author WilsonLee2000 + case "List": + List lists = new List(notes, toDo); + lists.listNotes(); + break; + //@@author WilsonLee2000 + case "Delete": + Delete deletes = new Delete(notes, toDo); + deletes.deleteNotes(); + break; + //@@author WilsonLee2000 + case "History": + commandHist.displayHistory(); + break; + //@@author ZiqiuZeng + case "Mark": + notesMarker.mark(toDo); + break; + //@@author ZiqiuZeng + case "Unmark": + notesMarker.unmark(toDo); + break; + //@@author ZiqiuZeng + case "Low": + case "Medium": + case "High": + prioritySetter.setPriority(command,toDo); + break; + //@@author ZiqiuZeng + case "FindInfo": + notesFinder.find(toDo); + break; + //@@author ZiqiuZeng + case "FindPrior": + notesPriorityFinder.find(toDo); + break; + //@@author ZiqiuZeng + case "FindMark": + Ui.printFindNotes(notes.relevantMarked()); + break; + //@@author ZiqiuZeng + case "FindUnmark": + Ui.printFindNotes(notes.relevantUnmarked()); + break; + //@@author ZiqiuZeng + case "Rank": + notesRanker.rank(toDo); + break; + /* + * The command "Clear" will continue to execute for as long as it is being entered, + * without any other command or input interrupting it. + */ + case "Clear": + notes.reset(); + NotesFileCleaner.clearFile(filePath); + break; + /* + * The command "Help" will continue to execute for as long as it is being entered, + * without any other command or input interrupting it. + */ + case "Help": + HelpManual.readHelpManual(); + break; + //@@author 0nandon + case "Matrix": + calculator.run(toDo); + break; + //@@author Khooyourun + case "Quadratic": + quadratic.solveQuadratic(); + break; + default: + break; + } + } catch (IllegalIndexException e) { + System.out.println("Oops! This note does not exist. Please try again."); + } catch (IllegalTodoException e) { + Ui.printIncorrectFormatEntered(); + } + + Ui.printLineBreak(); + } +} + diff --git a/src/main/java/seedu/badmaths/CommandHistory.java b/src/main/java/seedu/badmaths/CommandHistory.java new file mode 100644 index 0000000000..d17fee29b5 --- /dev/null +++ b/src/main/java/seedu/badmaths/CommandHistory.java @@ -0,0 +1,33 @@ +//@@author WilsonLee2000 + +/** + * Takes in an ArrayList containing previous history commands that the user have entered so far + * during the current programme run session. + * Prints out a list of history commands from the ArrayList if function is called. + * + * @param historyCommand + */ + +package seedu.badmaths; +import java.util.ArrayList; + +public class CommandHistory { + + ArrayList historyCommand = new ArrayList<>(); + + public CommandHistory(ArrayList historyCommand) { + this.historyCommand = historyCommand; + } + + public void storeCommand(String inputCommand) { + historyCommand.add(inputCommand); + } + + public void displayHistory() { + System.out.println("Here are the list of commands that you have entered so far:"); + for (String command : historyCommand) { + System.out.println(command); + } + System.out.println(); + } +} diff --git a/src/main/java/seedu/badmaths/Delete.java b/src/main/java/seedu/badmaths/Delete.java new file mode 100644 index 0000000000..f5c73847f1 --- /dev/null +++ b/src/main/java/seedu/badmaths/Delete.java @@ -0,0 +1,59 @@ +//@@author WilsonLee2000 + +/** + * Takes in an index that is being input by users. + * Deletes an item from the notes based on the index that is being provided by users. + * + * @param notes + * @param toDo + */ + +package seedu.badmaths; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.storage.NotesFileWriter; +import seedu.badmaths.ui.Ui; + +public class Delete { + + private static final String filePath = "data/notes.txt"; + public NotesList notes; + protected String toDo; + + public Delete (NotesList notes, String toDo) { + this.toDo = toDo; + this.notes = notes; + } + + public static boolean isInvalidIndex(int index, NotesList notes) { + return (index < 0 || index >= notes.getSize()); + } + + public static boolean isAnInt(String todo) { + try { + Integer.parseInt(todo); + } catch (NumberFormatException numberException) { + Ui.printInvalidNumberEntered(); + return false; + } + return true; + } + + public void deleteNotes() { + try { + if (!isAnInt(toDo)) { + throw new IllegalTodoException(); + } + int deleteIndex = Integer.parseInt(toDo) - 1; + if (isInvalidIndex(deleteIndex, notes)) { + throw new IllegalIndexException(); + } + Ui.printDelete(notes.getText(deleteIndex), notes.getSize()); + notes.remove(deleteIndex); + NotesFileWriter.saveFile(filePath, notes.getAll()); + } catch (IllegalIndexException exceptionIndex) { + System.out.println("Oops! This note does not exist. Please try again."); + } catch (IllegalTodoException exceptionTodo) { + Ui.printIncorrectFormatEntered(); + } + } +} diff --git a/src/main/java/seedu/badmaths/HelpManual.java b/src/main/java/seedu/badmaths/HelpManual.java new file mode 100644 index 0000000000..e51c6d4d65 --- /dev/null +++ b/src/main/java/seedu/badmaths/HelpManual.java @@ -0,0 +1,69 @@ +/** + * Provides the HelpManual to guide users who are operating BadMaths. + */ + +package seedu.badmaths; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.BufferedReader; + +import java.util.logging.LogManager; +import java.util.logging.Logger; +import java.util.logging.Level; + + +public class HelpManual { + protected static String filePath = "/HelpManual.txt"; // file path relative to the classpath + protected static String logFilePath = "Help"; + private static final Logger logger = Logger.getLogger(logFilePath); + + public static void setUpLogger() { + LogManager.getLogManager().reset(); + logger.setLevel(Level.ALL); + try { + if (!new File(logFilePath).exists()) { + new File(logFilePath).createNewFile(); + } + } catch (IOException e) { + logger.log(Level.SEVERE, "File logger not working", e); + } + } + + /** + * This method reads the content from HelpManual.txt file. + */ + public static void readHelpManual() { + setUpLogger(); + try { + logger.log(Level.INFO, "going to start processing"); + InputStream inputStream = HelpManual.class.getResourceAsStream(filePath); + + // assert that the input stream is not null + assert inputStream != null : "Invalid file: " + filePath; + + InputStreamReader read = new InputStreamReader(inputStream, "UTF-8"); + BufferedReader bufferedReader = new BufferedReader(read); + + String lineTxt; + StringBuilder content = new StringBuilder(); + + while ((lineTxt = bufferedReader.readLine()) != null) { + content.append(lineTxt).append("\n"); + System.out.println(lineTxt); + } + bufferedReader.close(); + read.close(); + + // Log successful read to console and log file + logger.log(Level.INFO, "Successfully read Help Manual file."); + + } catch (Exception e) { + System.out.println("Error while loading files. Please try again."); + logger.severe("Error while loading Help Manual. Please try again."); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/seedu/badmaths/IllegalIndexException.java b/src/main/java/seedu/badmaths/IllegalIndexException.java new file mode 100644 index 0000000000..ff9daa906d --- /dev/null +++ b/src/main/java/seedu/badmaths/IllegalIndexException.java @@ -0,0 +1,4 @@ +package seedu.badmaths; + +public class IllegalIndexException extends Exception{ +} diff --git a/src/main/java/seedu/badmaths/IllegalTodoException.java b/src/main/java/seedu/badmaths/IllegalTodoException.java new file mode 100644 index 0000000000..4d7953d889 --- /dev/null +++ b/src/main/java/seedu/badmaths/IllegalTodoException.java @@ -0,0 +1,4 @@ +package seedu.badmaths; + +public class IllegalTodoException extends Exception{ +} diff --git a/src/main/java/seedu/badmaths/InvalidFormatException.java b/src/main/java/seedu/badmaths/InvalidFormatException.java new file mode 100644 index 0000000000..2850184d69 --- /dev/null +++ b/src/main/java/seedu/badmaths/InvalidFormatException.java @@ -0,0 +1,4 @@ +package seedu.badmaths; + +public class InvalidFormatException extends Throwable { +} diff --git a/src/main/java/seedu/badmaths/List.java b/src/main/java/seedu/badmaths/List.java new file mode 100644 index 0000000000..b770543693 --- /dev/null +++ b/src/main/java/seedu/badmaths/List.java @@ -0,0 +1,66 @@ +//@@author WilsonLee2000 + +/** + * Takes in an index that is being input by users, for displaying of items from notes list. + * Prints out an item from the notes based on the index that is being provided by users. + * Alternatively, if index is not provided by users, prints out a list of all items from the notes. + * + * @param notes + * @param toDo + */ + +package seedu.badmaths; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.ui.Ui; + +public class List { + + public NotesList notes; + protected String toDo; + + public List(NotesList notes, String toDo) { + this.notes = notes; + this.toDo = toDo; + } + + public boolean isInvalidIndex(int index, NotesList notes) { + return (index < 0 || index >= notes.getSize()); + } + + public boolean isInvalidTodo(String todo) { + return todo.equals("Invalid todo"); + } + + public boolean isAnInt(String todo) { + try { + Integer.parseInt(todo); + } catch (NumberFormatException numberException) { + Ui.printInvalidNumberEntered(); + return false; + } + return true; + } + + public void listNotes() { + try { + if ((!isInvalidTodo(toDo)) && (!isAnInt(toDo))) { + throw new IllegalTodoException(); + } + if (isInvalidTodo(toDo)) { + Ui.printNotes(notes.getAll()); + return; + } + int index = Integer.parseInt(toDo) - 1; + + if (isInvalidIndex(index, notes)) { + throw new IllegalIndexException(); + } + notes.review(index); + Ui.printSpecificNote(index, notes.getAll()); + } catch (IllegalIndexException exceptionIndex) { + System.out.println("Oops! This note does not exist. Please try again."); + } catch (IllegalTodoException exceptionTodo) { + Ui.printIncorrectFormatEntered(); + } + } +} diff --git a/src/main/java/seedu/badmaths/Parser.java b/src/main/java/seedu/badmaths/Parser.java new file mode 100644 index 0000000000..1690c1e849 --- /dev/null +++ b/src/main/java/seedu/badmaths/Parser.java @@ -0,0 +1,65 @@ +/** + * Takes in user input and splits it into 2 parts + * First part is the function name + * Second part is the todo to be executed in that function + * Returns the two parts using get methods + * + * @param userInput + */ + +package seedu.badmaths; + +import seedu.badmaths.ui.Ui; + +public class Parser { + + protected String userInput; + + public Parser(String userInput) { // List. 1 + this.userInput = userInput; + } + + /** + * Separates the first word of user input which is the command + * Throws an exception if there is format error in the input + * @return command + */ + public String getCommand() { + try { + String trimmedInput = userInput.trim(); + if (trimmedInput.contains(" ")) { + int indexOfSpace = trimmedInput.indexOf(" "); + String command = trimmedInput.substring(0, indexOfSpace); + return command; + } else { + return userInput; + } + } catch (IllegalArgumentException e) { + Ui.printIncorrectFormatEntered(); + return null; + } + } + + /** + * Separates all the words other than the first from user input which would be toDo + * If there is only 1 word (ie no toDo), then "Invalid toDo" would be returned + * Throws an exception if there is format error + * @return toDo + */ + public String getToDo() { + try { + String[] parts = userInput.trim().split(" ", 2); + if (parts.length == 1) { + return "Invalid todo"; // means there is no todo + } else { + return parts[1].trim(); + } + } catch (IllegalArgumentException e) { + Ui.printIncorrectFormatEntered(); + return null; + } + } +} + + + diff --git a/src/main/java/seedu/badmaths/Quadratic/Quadratic.java b/src/main/java/seedu/badmaths/Quadratic/Quadratic.java new file mode 100644 index 0000000000..ca17acd77e --- /dev/null +++ b/src/main/java/seedu/badmaths/Quadratic/Quadratic.java @@ -0,0 +1,78 @@ +/** + * Takes in a quadratic equation and calculates the values of x + * Prints out the x values if real, and notifies user if its imaginary + * + * Contains a String toDo which is the quadratic equation + */ + +package seedu.badmaths.Quadratic; +import java.util.ArrayList; +import seedu.badmaths.ui.Ui; + +public class Quadratic { + + protected static String toDo; + + public Quadratic (String toDo) { + Quadratic.toDo = toDo; + } + + /** + * Solves the quadratic equation, Ax^2 + Bx + C, to get 2 values of x + * @param A which is the A value + * @param B which is the B value + * @param C which is the C value + * @return xStore which is an ArrayList of Doubles containing 2 elements, the two values of x + */ + public ArrayList quadraticFormula(double A, double B, double C) { + double x1 = (-B + Math.sqrt(B * B - 4 * A * C)) / (2 * A); + double x2 = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); + ArrayList xStore = new ArrayList<>(); + xStore.add(x1); + xStore.add(x2); + return xStore; + } + + /** + * Finds the coordinates of the minimum or maximum point of the quadratic equation, Ax^2 + Bx + C + * @param A which is the A value + * @param B which is the B value + * @param C which is the C value + * @return the coordinates in the form of a string: (x,y) + */ + public String minMaxPointFinder(double A, double B, double C) { + double xCoordinate = (-B) / (2 * A); + double yCoordinate = (A * (xCoordinate * xCoordinate)) + (B * xCoordinate) + C; + String stringofXCoor = Double.toString(xCoordinate); + String stringOfYCoor = Double.toString(yCoordinate); + return "(" + stringofXCoor + (", ") + stringOfYCoor + ")"; + } + + public void printAnswer(ArrayList xStore, String vertextCoordinate, boolean isMinimum) { + Ui.printQuadraticAnswer(xStore, vertextCoordinate, isMinimum); + } + + /** + * Calls the above methods to find and print the answer to the quadratic equation + * Catches possible exceptions and prints an error message + */ + public void solveQuadratic() { + try { + double A = QuadraticParser.findA(); + double B = QuadraticParser.findB(); + double C = QuadraticParser.findC(); + boolean isMinimum; + if (A > 0) { + isMinimum = true; + } else { + isMinimum = false; + } + ArrayList xStore; + xStore = quadraticFormula(A, B, C); + String vertexCoordinate = minMaxPointFinder(A, B, C); + printAnswer(xStore, vertexCoordinate, isMinimum); + } catch (NumberFormatException | IndexOutOfBoundsException e) { + Ui.printQuadraticFormatError(); + } + } +} diff --git a/src/main/java/seedu/badmaths/Quadratic/QuadraticParser.java b/src/main/java/seedu/badmaths/Quadratic/QuadraticParser.java new file mode 100644 index 0000000000..a7fdb01027 --- /dev/null +++ b/src/main/java/seedu/badmaths/Quadratic/QuadraticParser.java @@ -0,0 +1,102 @@ +package seedu.badmaths.Quadratic; + +public class QuadraticParser extends Quadratic { + + private static final int POSITIVE = 1; + private static final int NEGATIVE = -1; + private static final String ADDITION = "+"; + private static final String SUBTRACTION = "-"; + private static final int INDEX_MODIFIER_2 = 2; + private static final int INDEX_MODIFIER_3 = 3; + private static final int INDEX_MODIFIER_4 = 4; + private static final int INDEX_MODIFIER_5 = 5; + + public QuadraticParser(String toDo) { + super(toDo); + } + + /** + * Identifies A from Ax^2 + Bx + C + * @return A as a double data type + */ + public static double findA() { + String stringA = toDo.substring(0, toDo.indexOf("x")); + if (stringA.equals(SUBTRACTION)) { + return NEGATIVE; + } else { + if (stringA.isEmpty()) { + return POSITIVE; + } else { + return Double.parseDouble(stringA); + } + } + } + + /** + * Identifies the sign of B (+ or -) + * @return the sign as a String + */ + public static String findSignOfB() { + int startIndexOfSign = toDo.indexOf("^2") + INDEX_MODIFIER_3; + int endIndexOfSign = toDo.indexOf("^2") + INDEX_MODIFIER_4; + return toDo.substring(startIndexOfSign, endIndexOfSign); + } + + public static String findStringOfB() { + int startIndexOfB = toDo.indexOf("^2") + INDEX_MODIFIER_5; + int endIndexOfB = toDo.indexOf("x "); + return toDo.substring(startIndexOfB, endIndexOfB); + } + + /** + * Identifies B from Ax^2 + Bx + C + * @return A as a double data type + */ + public static double findB() { + String sign = findSignOfB(); + String stringB = findStringOfB(); + if (stringB.isEmpty()) { + if (sign.equals(ADDITION)) { + return POSITIVE; + } else { + return NEGATIVE; + } + } else { + if (sign.equals(ADDITION)) { + return Double.parseDouble(stringB); + } else { + return Double.parseDouble(stringB) * NEGATIVE; + } + } + } + + /** + * Identifies the sign of C (+ or -) + * @return the sign as a String + */ + public static String findSignOfC() { + int startIndexOfSign = toDo.indexOf("x ") + INDEX_MODIFIER_2; + int endIndexOfSign = toDo.indexOf("x ") + INDEX_MODIFIER_3; + return toDo.substring(startIndexOfSign, endIndexOfSign); + } + + public static String findStringOfC() { + int indexOfC = toDo.indexOf("x ") + INDEX_MODIFIER_4; + return toDo.substring(indexOfC); + } + + /** + * Identifies C from Ax^2 + Bx + C + * @return C as a double data type + */ + public static double findC() { + String sign = findSignOfC(); + String stringC = findStringOfC(); + double C = Double.parseDouble(stringC); + if (sign.equals(ADDITION)) { + return C; + } else { + return C * NEGATIVE; + } + } +} diff --git a/src/main/java/seedu/badmaths/Store.java b/src/main/java/seedu/badmaths/Store.java new file mode 100644 index 0000000000..9580c0f6f7 --- /dev/null +++ b/src/main/java/seedu/badmaths/Store.java @@ -0,0 +1,46 @@ +//@@author WilsonLee2000 + +/** + * Takes in a String toDo and stores the toDo String provided by users into the notes list. + * + * @param notes + * @param toDo + */ + +package seedu.badmaths; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.storage.NotesFileWriter; +import seedu.badmaths.ui.Ui; + +public class Store { + + private static final String filePath = "data/notes.txt"; + public NotesList notes; + protected String toDo; + + public Store(NotesList notes, String toDo) { + this.toDo = toDo; + this.notes = notes; + } + + public static boolean isInvalidTodo(String todo) { + return todo.equals("Invalid todo"); + } + + public void storeNotes() { + try { + if (isInvalidTodo(toDo)) { + throw new IllegalTodoException(); + } + if (toDo.equals("null")) { + throw new IllegalTodoException(); + } + notes.add(toDo); + Ui.printAddNote(toDo, notes.getSize()); + NotesFileWriter.saveFile(filePath, notes.getAll()); + } catch (IllegalTodoException exception) { + Ui.printIncorrectFormatEntered(); + } + } +} + diff --git a/src/main/java/seedu/badmaths/commands/IndexChecker.java b/src/main/java/seedu/badmaths/commands/IndexChecker.java new file mode 100644 index 0000000000..83b18c8327 --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/IndexChecker.java @@ -0,0 +1,9 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.note.NotesList; + +public class IndexChecker { + public static boolean isInvalidIndex(int index, NotesList notes) { + return index < 0 || index >= notes.getSize(); + } +} diff --git a/src/main/java/seedu/badmaths/commands/IntegerChecker.java b/src/main/java/seedu/badmaths/commands/IntegerChecker.java new file mode 100644 index 0000000000..eb6150a714 --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/IntegerChecker.java @@ -0,0 +1,15 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.ui.Ui; + +public class IntegerChecker { + public static boolean isAnInt(String str) { + try { + Integer.parseInt(str); + return true; + } catch (NumberFormatException e) { + Ui.printInvalidNumberEntered(); + return false; + } + } +} diff --git a/src/main/java/seedu/badmaths/commands/NotesFinder.java b/src/main/java/seedu/badmaths/commands/NotesFinder.java new file mode 100644 index 0000000000..23abe6b228 --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/NotesFinder.java @@ -0,0 +1,29 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.IllegalTodoException; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.ui.Ui; + +import java.util.ArrayList; + +import static seedu.badmaths.Store.isInvalidTodo; + +public class NotesFinder { + private NotesList notes; + private String filePath; + + public NotesFinder(NotesList notes, String filePath) { + this.notes = notes; + this.filePath = filePath; + } + + public void find(String keyword) throws IllegalTodoException { + if (isInvalidTodo(keyword)) { + throw new IllegalTodoException(); + } + + ArrayList relevantNotes = notes.relevantInfo(keyword); + Ui.printFindNotes(relevantNotes); + } +} diff --git a/src/main/java/seedu/badmaths/commands/NotesMarker.java b/src/main/java/seedu/badmaths/commands/NotesMarker.java new file mode 100644 index 0000000000..a6788d15d9 --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/NotesMarker.java @@ -0,0 +1,50 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.IllegalIndexException; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.storage.NotesFileWriter; +import seedu.badmaths.ui.Ui; + +import static seedu.badmaths.commands.IntegerChecker.isAnInt; +import static seedu.badmaths.commands.IndexChecker.isInvalidIndex; + +public class NotesMarker { + private NotesList notes; + private String filePath; + + public NotesMarker(NotesList notes, String filePath) { + this.notes = notes; + this.filePath = filePath; + } + + public void mark(String toDo) throws IllegalIndexException { + if (!isAnInt(toDo)) { + return; + } + + int markIndex = Integer.parseInt(toDo) - 1; + if (isInvalidIndex(markIndex, notes)) { + throw new IllegalIndexException(); + } + + notes.markAsDone(markIndex); + Ui.printMark(notes.getText(markIndex)); + NotesFileWriter.saveFile(filePath, notes.getAll()); + } + + public void unmark(String toDo) throws IllegalIndexException { + if (!isAnInt(toDo)) { + return; + } + + int unmarkIndex = Integer.parseInt(toDo) - 1; + if (isInvalidIndex(unmarkIndex, notes)) { + throw new IllegalIndexException(); + } + + notes.markAsUndone(unmarkIndex); + Ui.printUnmark(notes.getText(unmarkIndex)); + NotesFileWriter.saveFile(filePath, notes.getAll()); + } + +} diff --git a/src/main/java/seedu/badmaths/commands/NotesPriorityFinder.java b/src/main/java/seedu/badmaths/commands/NotesPriorityFinder.java new file mode 100644 index 0000000000..53b7a2a9ac --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/NotesPriorityFinder.java @@ -0,0 +1,31 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.IllegalTodoException; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.ui.Ui; + +import java.util.ArrayList; + +public class NotesPriorityFinder { + private NotesList notes; + private String filePath; + + public NotesPriorityFinder(NotesList notes, String filePath) { + this.notes = notes; + this.filePath = filePath; + } + + public void find(String priorityStr) throws IllegalTodoException{ + switch (priorityStr.toLowerCase()) { + case "low": + case "medium": + case "high": + ArrayList relevantNotes = notes.relevantPriority(priorityStr.toUpperCase()); + Ui.printFindNotes(relevantNotes); + break; + default: + throw new IllegalTodoException(); + } + } +} diff --git a/src/main/java/seedu/badmaths/commands/NotesRanker.java b/src/main/java/seedu/badmaths/commands/NotesRanker.java new file mode 100644 index 0000000000..edf99b31a8 --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/NotesRanker.java @@ -0,0 +1,34 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.IllegalTodoException; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.storage.NotesFileWriter; +import seedu.badmaths.ui.Ui; + +public class NotesRanker { + private NotesList notes; + private String filePath; + + public NotesRanker(NotesList notes, String filePath) { + this.notes = notes; + this.filePath = filePath; + } + + public void rank(String toDo) throws IllegalTodoException { + switch (toDo) { + case "Review Count": + notes.rankByReviewCount(); + Ui.printNotesByReviewCount(notes.getAll()); + NotesFileWriter.saveFile(filePath, notes.getAll()); + break; + case "Priority": + notes.rankByPriority(); + Ui.printNotesByPriority(notes.getAll()); + NotesFileWriter.saveFile(filePath, notes.getAll()); + break; + default: + throw new IllegalTodoException(); + } + } + +} diff --git a/src/main/java/seedu/badmaths/commands/PrioritySetter.java b/src/main/java/seedu/badmaths/commands/PrioritySetter.java new file mode 100644 index 0000000000..bdcc0b3d40 --- /dev/null +++ b/src/main/java/seedu/badmaths/commands/PrioritySetter.java @@ -0,0 +1,37 @@ +package seedu.badmaths.commands; + +import seedu.badmaths.IllegalIndexException; +import seedu.badmaths.note.NotesList; +import seedu.badmaths.note.NotePriority; +import seedu.badmaths.storage.NotesFileWriter; +import seedu.badmaths.ui.Ui; + +import static seedu.badmaths.commands.IntegerChecker.isAnInt; +import static seedu.badmaths.commands.IndexChecker.isInvalidIndex; + +public class PrioritySetter { + private NotesList notes; + private String filePath; + + public PrioritySetter(NotesList notes, String filePath) { + this.notes = notes; + this.filePath = filePath; + } + + public void setPriority(String priorityString, String toDo) throws IllegalIndexException { + if (!isAnInt(toDo)) { + return; + } + + int index = Integer.parseInt(toDo) - 1; + if (isInvalidIndex(index, notes)) { + throw new IllegalIndexException(); + } + + NotePriority.Priority priority = NotePriority.Priority.valueOf(priorityString.toUpperCase()); + + notes.setPriority(index, priority); + Ui.printPriority(index, notes.getAll()); + NotesFileWriter.saveFile(filePath, notes.getAll()); + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Calculate.java b/src/main/java/seedu/badmaths/matrix/Calculate.java new file mode 100644 index 0000000000..36a5f82c1c --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Calculate.java @@ -0,0 +1,137 @@ +package seedu.badmaths.matrix; + +import seedu.badmaths.matrix.exception.ExceptionChecker; +import seedu.badmaths.matrix.exception.ExceptionPrinter; +import seedu.badmaths.matrix.exception.ShapeMismatchException; + +import java.util.logging.Logger; + +/** + * This class calculates the various matrix calculation below: + * 1. Matrix multiplication + * 2. Matrix element wise product + * 3. Matrix subtraction + * 4. Matrix addition + */ +public class Calculate { + ExceptionChecker check = new ExceptionChecker(); + Logger logger = Logger.getLogger("Exception"); + ExceptionPrinter ep = new ExceptionPrinter(); + + /** + * Calculate the matrix multiplication. + * + * @param t1 operand1 + * @param t2 operand2 + */ + public Tensor2D mul(Tensor2D t1, Tensor2D t2) { + Shape t1Shape = t1.shape(); + Shape t2Shape = t2.shape(); + + try{ + check.checkShapeMismatch(t1, t2, "MUL"); + + Tensor2D t2T = t2.t(); + int[][] output = new int[t1Shape.row][t2Shape.column]; + + for(int i = 0; i < t1Shape.row; i++) { + for(int j = 0; j < t2Shape.column; j++) { + output[i][j] = 0; + + for(int k = 0; k < t1Shape.column; k++) { + output[i][j] += t1.get(i, k) * t2T.get(j, k); + } + } + } + + return new Tensor2D(output); + } catch (ShapeMismatchException e) { + ep.printShapeMismatchExceptionLog(); + return null; + } + } + + /** + * Calculate the matrix element wise product. + * + * @param t1 operand1 + * @param t2 operand2 + */ + public Tensor2D dot(Tensor2D t1, Tensor2D t2) { + Shape t1Shape = t1.shape(); + Shape t2Shape = t2.shape(); + + try { + check.checkShapeMismatch(t1, t2, "DOT"); + + int[][] output = new int[t1Shape.row][t1Shape.column]; + + for(int i = 0; i < t1Shape.row; i++) { + for(int j = 0; j < t1Shape.column; j++) { + output[i][j] = t1.get(i, j) * t2.get(i, j); + } + } + + return new Tensor2D(output); + } catch (ShapeMismatchException e) { + ep.printShapeMismatchExceptionLog(); + return null; + } + } + + /** + * Calculate the matrix addition. + * + * @param t1 operand1 + * @param t2 operand2 + */ + public Tensor2D add(Tensor2D t1, Tensor2D t2) { + Shape t1Shape = t1.shape(); + Shape t2Shape = t2.shape(); + + try { + check.checkShapeMismatch(t1, t2, "ADD"); + + int[][] output = new int[t1Shape.row][t1Shape.column]; + + for(int i = 0; i < t1Shape.row; i++) { + for(int j = 0; j < t1Shape.column; j++) { + output[i][j] = t1.get(i, j) + t2.get(i, j); + } + } + + return new Tensor2D(output); + } catch (ShapeMismatchException e) { + ep.printShapeMismatchExceptionLog(); + return null; + } + } + + /** + * Calculate the matrix subtraction. + * + * @param t1 operand1 + * @param t2 operand2 + */ + public Tensor2D sub(Tensor2D t1, Tensor2D t2) { + Shape t1Shape = t1.shape(); + Shape t2Shape = t2.shape(); + + try { + check.checkShapeMismatch(t1, t2, "SUB"); + + int[][] output = new int[t1Shape.row][t1Shape.column]; + + for(int i = 0; i < t1Shape.row; i++) { + for(int j = 0; j < t1Shape.column; j++) { + output[i][j] = t1.get(i, j) - t2.get(i, j); + } + } + + return new Tensor2D(output); + } catch (ShapeMismatchException e) { + ep.printShapeMismatchExceptionLog(); + return null; + } + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Calculator.java b/src/main/java/seedu/badmaths/matrix/Calculator.java new file mode 100644 index 0000000000..60a3a161d8 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Calculator.java @@ -0,0 +1,29 @@ +package seedu.badmaths.matrix; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class runs the given Matrix command. + */ +public class Calculator { + Logger logger = Logger.getLogger("matrix"); + + /** + * Run the Matrix command. + * + * @param toDo given matrix expression. + */ + public void run(String toDo) { + logger.log(Level.INFO, "Start to open calculator."); + + Ui ui = new Ui(); + Parser p = new Parser(); + Tensor2D result; + + result = p.parse(toDo); + if(result != null) { + ui.printResult(result); + } + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Execute.java b/src/main/java/seedu/badmaths/matrix/Execute.java new file mode 100644 index 0000000000..eed918e492 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Execute.java @@ -0,0 +1,151 @@ +package seedu.badmaths.matrix; + +/** + * This class executes the given expression with given operators and operand parsed from Parser class. + */ +public class Execute { + + /** + * Execute the given command with calling corresponding executing function. + * + * @param type type of the operator. + * @param command given matrix expression. + */ + public Tensor2D execute(Parser.CalType type, String command){ + Tensor2D result = null; + + switch(type) { + case ADDITION: + result = executeAdd(command); + break; + case SUBTRACTION: + result = executeSub(command); + break; + case MULTIPLICATION: + result = executeMul(command); + break; + case ELEMENT_WISE_DOT_PRODUCT: + result = executeDot(command); + break; + default: + break; + } + + return result; + } + + /** + * Execute the matrix multiplication with calling corresponding function from Calculate class. + * + * @param command given matrix expression. + */ + public Tensor2D executeMul(String command) { + Calculate c = new Calculate(); + + String[] operator = command.split("\\.\\*"); + + Tensor2D result; + Tensor2D t1 = executeTranspose(operator[0]); + Tensor2D t2 = executeTranspose(operator[1]); + + if(t1 == null || t2 == null){ + return null; + } + + result = c.mul(t1, t2); + assert result != null; + + return result; + } + + /** + * Execute the matrix element wise product with calling corresponding function from Calculate class. + * + * @param command given matrix expression. + */ + public Tensor2D executeDot(String command) { + Calculate c = new Calculate(); + + String[] operator = command.split("\\*"); + + Tensor2D result; + Tensor2D t1 = executeTranspose(operator[0]); + Tensor2D t2 = executeTranspose(operator[1]); + + if(t1 == null || t2 == null){ + return null; + } + + result = c.dot(t1, t2); + assert result != null; + + return result; + } + + /** + * Execute the matrix addition with calling corresponding function from Calculate class. + * + * @param command given matrix expression. + */ + public Tensor2D executeAdd(String command) { + Calculate c = new Calculate(); + + String[] operator = command.split("\\+"); + + Tensor2D result; + Tensor2D t1 = executeTranspose(operator[0]); + Tensor2D t2 = executeTranspose(operator[1]); + + if(t1 == null || t2 == null){ + return null; + } + + result = c.add(t1, t2); + assert result != null; + + return result; + } + + /** + * Execute the matrix subtraction with calling corresponding function from Calculate class. + * + * @param command given matrix expression. + */ + public Tensor2D executeSub(String command) { + Calculate c = new Calculate(); + + String[] operator = command.split("-"); + + Tensor2D result; + Tensor2D t1 = executeTranspose(operator[0]); + Tensor2D t2 = executeTranspose(operator[1]); + + if(t1 == null || t2 == null){ + return null; + } + + result = c.sub(t1, t2); + assert result != null; + + return result; + } + + /** + * Execute the matrix transposition with calling corresponding function from Calculate class. + * + * @param command given matrix expression. + */ + public Tensor2D executeTranspose(String command) { + String operator; + Tensor2D output; + + if(command.contains(".T")) { + operator = command.replace(".T", ""); + output = Parser.parseMatrix(operator); + + return output != null ? output.t() : output; + } else { + return Parser.parseMatrix(command); + } + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Parser.java b/src/main/java/seedu/badmaths/matrix/Parser.java new file mode 100644 index 0000000000..e2b545a180 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Parser.java @@ -0,0 +1,114 @@ +package seedu.badmaths.matrix; + + +import seedu.badmaths.matrix.exception.ExceptionChecker; +import seedu.badmaths.matrix.exception.ExceptionPrinter; +import seedu.badmaths.matrix.exception.UnknownOperatorException; +import seedu.badmaths.matrix.exception.MatrixShapeException; +import seedu.badmaths.matrix.exception.MatrixFormatException; + +/** + * This class parses the given expression with extracting operands and operator. + * It also calls the corresponding function from Execute class. + */ +public class Parser { + static ExceptionChecker check = new ExceptionChecker(); + static ExceptionPrinter ep = new ExceptionPrinter(); + + /** + * Parse the given command and execute it with returning the output. + * + * @param command given matrix expression. + */ + public Tensor2D parse(String command) { + CalType type; + Tensor2D result; + Execute ex = new Execute(); + + command = command.replace(" ", ""); + + try { + check.checkUnknownOperator(command); + + type = parseOp(command); + result = ex.execute(type, command); + + return result; + } catch (UnknownOperatorException e) { + ep.printUnknownOperatorExceptionLog(); + return null; + } + } + + /** + * Parse the given command with discovering the type of operator. + * Return the corresponding CalType. + * + * @param command given matrix expression. + */ + protected CalType parseOp(String command){ + if(command.contains("]+[")) { + return CalType.ADDITION; + } else if(command.contains("]-[")) { + return CalType.SUBTRACTION; + } else if(command.contains("].*[")) { + return CalType.MULTIPLICATION; + } else if(command.contains("]*[")) { + return CalType.ELEMENT_WISE_DOT_PRODUCT; + } else { + return CalType.UNKNOWN; + } + } + + /** + * Parse the matrix to Tensor2D class. + * + * @param command given matrix expression. + */ + public static Tensor2D parseMatrix(String command) { + int[][] tensor; + int rowNum; + int colNum; + + try { + check.checkMatrixFormat(command); + + command = command.replace("[", ""); + command = command.replace("]", ""); + + String[] rows; + String[] column; + + rows = command.split(";"); + rowNum = rows.length; + colNum = rows[0].split(",").length; + + assert rowNum == 1 || colNum == rows[1].split(",").length; + + tensor = new int[rowNum][colNum]; + for (int i = 0; i < rowNum; i++) { + column = rows[i].split(","); + for (int j = 0; j < colNum; j++) { + try { + tensor[i][j] = Integer.parseInt(column[j]); + } catch (NumberFormatException e) { + ep.printMatrixNumericExceptionLog(); + return null; + } + } + } + } catch (MatrixFormatException fe) { + ep.printMatrixFormatExceptionLog(); + return null; + } catch (MatrixShapeException se) { + ep.printMatrixShapeExceptionLog(); + return null; + } + + return new Tensor2D(tensor); + } + + enum CalType { + ADDITION, SUBTRACTION, MULTIPLICATION, ELEMENT_WISE_DOT_PRODUCT, UNKNOWN + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Shape.java b/src/main/java/seedu/badmaths/matrix/Shape.java new file mode 100644 index 0000000000..b1457eda17 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Shape.java @@ -0,0 +1,42 @@ +package seedu.badmaths.matrix; + +/** + * Representation of the shape of the matrix. + */ +public class Shape { + protected int row; + protected int column; + + /** + * Create new shape class with the specified configuration. + * + * @param row the number of the row of 2D matrix. + * @param column the number of the column of 2D matrix. + */ + public Shape(int row, int column) { + this.row = row; + this.column = column; + } + + /** + * Return the row. + */ + public int getRow(){ + return row; + } + + /** + * Return the column. + */ + public int getColumn(){ + return column; + } + + /** + * Print the configuration of the Shape class. + */ + @Override + public String toString() { + return row + " x " + column; + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Tensor.java b/src/main/java/seedu/badmaths/matrix/Tensor.java new file mode 100644 index 0000000000..3853be6d21 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Tensor.java @@ -0,0 +1,7 @@ +package seedu.badmaths.matrix; + +public abstract class Tensor { + public abstract Shape shape(); + public abstract String toString(); +} + diff --git a/src/main/java/seedu/badmaths/matrix/Tensor2D.java b/src/main/java/seedu/badmaths/matrix/Tensor2D.java new file mode 100644 index 0000000000..e5468f06c1 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Tensor2D.java @@ -0,0 +1,95 @@ +package seedu.badmaths.matrix; + +/** + * Representation of the 2D matrix class. + */ +public class Tensor2D extends Tensor { + protected int[][] tensor; + protected Shape shape; + + /** + * Create new Tensor2D class with the specified configuration. + * + * @param tensor 2D array of integer which is the value of the matrix. + */ + public Tensor2D(int[][] tensor){ + this.tensor = tensor; + shape = new Shape(tensor.length, tensor[0].length); + } + + /** + * Return the shape of the matrix. + */ + public Shape shape(){ + return shape; + } + + /** + * Return the number of row of matrix. + */ + public int row(){ + return shape.getRow(); + } + + /** + * Return the number of column of matrix. + */ + public int column(){ + return shape.getColumn(); + } + + /** + * Return the value of the matrix. + */ + public int[][] tensor(){ + return this.tensor; + } + + /** + * Return the value of the given index within the matrix. + */ + public int get(int row, int column){ + return tensor[row][column]; + } + + /** + * Return the transposed matrix. + */ + public Tensor2D t(){ + int row = shape.row; + int column = shape.column; + + int[][] transposeTensor = new int[column][row]; + + for(int i = 0; i < column; i++) { + for(int j = 0; j < row; j++) { + transposeTensor[i][j] = tensor[j][i]; + } + } + + return new Tensor2D(transposeTensor); + } + + /** + * Print the configuration of the Tensor2D. + */ + @Override + public String toString() { + int row = shape.row; + int column = shape.column; + + StringBuilder str = new StringBuilder(""); + str.append(" 1. shape : ").append(row).append(" x ").append(column).append("\n"); + str.append(" 2. value : \n"); + + for(int i = 0; i < row; i++) { + str.append(" ").append(i).append(") "); + for(int j = 0; j < column; j++){ + str.append(tensor[i][j]).append(" "); + } + str.append("\n"); + } + + return str.toString(); + } +} diff --git a/src/main/java/seedu/badmaths/matrix/Ui.java b/src/main/java/seedu/badmaths/matrix/Ui.java new file mode 100644 index 0000000000..d80f7a37cf --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/Ui.java @@ -0,0 +1,12 @@ +package seedu.badmaths.matrix; + +public class Ui { + public void printInfo(){ + System.out.println(""); + } + + public void printResult(Tensor2D tensor){ + System.out.println("Result."); + System.out.println(tensor); + } +} diff --git a/src/main/java/seedu/badmaths/matrix/exception/ExceptionChecker.java b/src/main/java/seedu/badmaths/matrix/exception/ExceptionChecker.java new file mode 100644 index 0000000000..f4ba0ede9e --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/exception/ExceptionChecker.java @@ -0,0 +1,93 @@ +package seedu.badmaths.matrix.exception; + +import seedu.badmaths.matrix.Tensor2D; + +/** + * This class checks whether exception would be occurred. + * This class handles four exceptions below: + * 1. MatrixFormatException + * 2. MatrixShapeException + * 3. ShapeMismatchException + * 4. UnknownOperatorException + */ +public class ExceptionChecker { + + /** + * Check whether shapes of the two operands match each other for the matrix calculation. + * + * @param t1 operand1 + * @param t2 operand2 + * @param type type of the operator + */ + public void checkShapeMismatch(Tensor2D t1, Tensor2D t2, String type) throws ShapeMismatchException { + switch(type) { + case "MUL": + if(t1.column() != t2.row()) { + throw new ShapeMismatchException(); + } + break; + case "DOT": + case "ADD": + case "SUB": + boolean isColumnMatch = t1.column() != t2.column(); + boolean isRowMatch = t1.row() != t2.row(); + + if(isColumnMatch || isRowMatch) { + throw new ShapeMismatchException(); + } + break; + default: + break; + } + } + + /** + * Check whether given operator is appropriate. + * + * @param command given matrix expression. + */ + public void checkUnknownOperator(String command) throws UnknownOperatorException { + boolean isMul = command.contains("].*["); + boolean isDot = command.contains("]*["); + boolean isAdd = command.contains("]+["); + boolean isSub = command.contains("]-["); + + if (!isMul && !isDot && !isAdd && !isSub) { + throw new UnknownOperatorException(); + } + } + + /** + * Check whether matrix format of the given expression is appropriate. + * + * @param matrix given matrix expression. + */ + public static void checkMatrixFormat(String matrix) throws MatrixShapeException, MatrixFormatException { + boolean isRightWrapper = matrix.contains("[") && matrix.contains("]"); + + if(!isRightWrapper) { + throw new MatrixFormatException(); + } + + matrix = matrix.replace("[", ""); + matrix = matrix.replace("]", ""); + + String[] rows; + String[] column; + int rowNum; + int colNum; + + rows = matrix.split(";"); + rowNum = rows.length; + colNum = rows[0].split(",").length; + + for(int i = 0; i < rowNum; i++) { + column = rows[i].split(","); + for(int j = 0; j < colNum; j++) { + if(colNum != column.length) { + throw new MatrixShapeException(); + } + } + } + } +} diff --git a/src/main/java/seedu/badmaths/matrix/exception/ExceptionPrinter.java b/src/main/java/seedu/badmaths/matrix/exception/ExceptionPrinter.java new file mode 100644 index 0000000000..66510ee114 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/exception/ExceptionPrinter.java @@ -0,0 +1,71 @@ +package seedu.badmaths.matrix.exception; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class prints the corresponding exception message. + */ +public class ExceptionPrinter { + Logger logger = Logger.getLogger("exception"); + + /** + * Print the exception message of ShapeMismatchException. + */ + public void printShapeMismatchExceptionLog() { + String ExceptionMessage = ""; + ExceptionMessage += "\n"; + ExceptionMessage += "There is shape mismatch between t1 and t2 : cannot execute matrix calculation."; + System.out.println(ExceptionMessage); + + logger.log(Level.WARNING, "shape mismatch occur."); + } + + /** + * Print the exception message of UnknownOperatorException. + */ + public void printUnknownOperatorExceptionLog() { + String ExceptionMessage = ""; + ExceptionMessage += "\n"; + ExceptionMessage += "Operator in expression is unknown."; + System.out.println(ExceptionMessage); + + logger.log(Level.WARNING, "Unknown operator."); + } + + /** + * Print the exception message of MatrixShapeException. + */ + public void printMatrixShapeExceptionLog(){ + String ExceptionMessage = ""; + ExceptionMessage += "\n"; + ExceptionMessage += "Length of every rows should be the same with each other."; + System.out.println(ExceptionMessage); + + logger.log(Level.WARNING, "shape of matrix is not correct."); + } + + /** + * Print the exception message of MatrixFormatException. + */ + public void printMatrixFormatExceptionLog(){ + String ExceptionMessage = ""; + ExceptionMessage += "\n"; + ExceptionMessage += "Format of matrix is not correct."; + System.out.println(ExceptionMessage); + + logger.log(Level.WARNING, "Format of matrix is not correct."); + } + + /** + * Print the exception message of NumericFormatException. + */ + public void printMatrixNumericExceptionLog(){ + String ExceptionMessage = ""; + ExceptionMessage += "\n"; + ExceptionMessage += "Every entities of matrix should be integer."; + System.out.println(ExceptionMessage); + + logger.log(Level.WARNING, "Format of matrix is not correct."); + } +} diff --git a/src/main/java/seedu/badmaths/matrix/exception/MatrixFormatException.java b/src/main/java/seedu/badmaths/matrix/exception/MatrixFormatException.java new file mode 100644 index 0000000000..c5b0a233fe --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/exception/MatrixFormatException.java @@ -0,0 +1,7 @@ +package seedu.badmaths.matrix.exception; + +/** + * Exception that occurs when the matrix format of the given expression is not correct. + */ +public class MatrixFormatException extends Exception{ +} diff --git a/src/main/java/seedu/badmaths/matrix/exception/MatrixShapeException.java b/src/main/java/seedu/badmaths/matrix/exception/MatrixShapeException.java new file mode 100644 index 0000000000..a65c47e413 --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/exception/MatrixShapeException.java @@ -0,0 +1,7 @@ +package seedu.badmaths.matrix.exception; + +/** + * Exception that occurs when the shape of the matrix is not correct. + */ +public class MatrixShapeException extends Exception { +} diff --git a/src/main/java/seedu/badmaths/matrix/exception/ShapeMismatchException.java b/src/main/java/seedu/badmaths/matrix/exception/ShapeMismatchException.java new file mode 100644 index 0000000000..f37794df6b --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/exception/ShapeMismatchException.java @@ -0,0 +1,7 @@ +package seedu.badmaths.matrix.exception; + +/** + * Exception that occurs when the shapes of the two operands don't match with each other. + */ +public class ShapeMismatchException extends Exception { +} diff --git a/src/main/java/seedu/badmaths/matrix/exception/UnknownOperatorException.java b/src/main/java/seedu/badmaths/matrix/exception/UnknownOperatorException.java new file mode 100644 index 0000000000..1f1438febf --- /dev/null +++ b/src/main/java/seedu/badmaths/matrix/exception/UnknownOperatorException.java @@ -0,0 +1,7 @@ +package seedu.badmaths.matrix.exception; + +/** + * Exception that occurs when the given operator is unknown. + */ +public class UnknownOperatorException extends Exception { +} diff --git a/src/main/java/seedu/badmaths/note/Note.java b/src/main/java/seedu/badmaths/note/Note.java new file mode 100644 index 0000000000..d057514795 --- /dev/null +++ b/src/main/java/seedu/badmaths/note/Note.java @@ -0,0 +1,69 @@ +package seedu.badmaths.note; + +//@@author ZiqiuZeng +public class Note { + private String text; // the note information + private int reviewCount; // how many times the note has been reviewed + private boolean isDone; // whether the note is marked as done or not + private NotePriority.Priority priority; // the priority of the note + + // constructor + public Note(String text, NotePriority.Priority priority) { + this.text = text; + this.reviewCount = 0; + this.isDone = false; + this.priority = priority; + } + + public Note() { + } + + // getters and setters + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public int getReviewCount() { + return reviewCount; + } + + public void incrementReviewCount() { + this.reviewCount++; + } + + public boolean getIsDone() { + return isDone; + } + public String getIsDoneIcon() { + return (isDone ? "Y" : "N"); // mark done task with X + } + + public void markAsDone() { + this.isDone = true; + } + + public void markAsNotDone() { + this.isDone = false; + } + + public NotePriority.Priority getPriority() { + return priority; + } + + public void setPriority(NotePriority.Priority priority) { + this.priority = priority; + } + + public void setReviewCount(int reviewCount) { + this.reviewCount = reviewCount; + } + + @Override + public String toString() { + return "[" + getPriority() + "]" + "[" +getIsDoneIcon() + "]" + "[" + getReviewCount() + "]" + getText(); + } +} diff --git a/src/main/java/seedu/badmaths/note/NotePriority.java b/src/main/java/seedu/badmaths/note/NotePriority.java new file mode 100644 index 0000000000..a1883ed846 --- /dev/null +++ b/src/main/java/seedu/badmaths/note/NotePriority.java @@ -0,0 +1,9 @@ +package seedu.badmaths.note; + +public class NotePriority { + public enum Priority { + LOW, + MEDIUM, + HIGH + } +} diff --git a/src/main/java/seedu/badmaths/note/NotesList.java b/src/main/java/seedu/badmaths/note/NotesList.java new file mode 100644 index 0000000000..5352762b51 --- /dev/null +++ b/src/main/java/seedu/badmaths/note/NotesList.java @@ -0,0 +1,137 @@ +package seedu.badmaths.note; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +//@@author ZiqiuZeng +public class NotesList { + + //@@author ZiqiuZeng + protected ArrayList notes; + + //@@author ZiqiuZeng + public NotesList(ArrayList notes) { + this.notes = notes; + } + + //@@author ZiqiuZeng + public void reset() { + notes.clear(); + notes = new ArrayList<>(); + } + + //@@author ZiqiuZeng + public void add(String text) { + NotePriority.Priority priority = NotePriority.Priority.LOW; + Note note = new Note(text, priority); + notes.add(note); + } + + //@@author ZiqiuZeng + public void remove(int index) { + notes.remove(index); + } + + //@@author ZiqiuZeng + public void markAsDone(int index) { + Note note = notes.get(index); + note.markAsDone(); + } + + //@@author ZiqiuZeng + public void markAsUndone(int index) { + Note note = notes.get(index); + note.markAsNotDone(); + } + + //@@author ZiqiuZeng + public void setPriority(int index, NotePriority.Priority priority) { + Note note = notes.get(index); + note.setPriority(priority); + } + + //@@author ZiqiuZeng + public String getText(int index) { + return notes.get(index).toString(); + } + + //@@author ZiqiuZeng + public void review(int index) { + Note note = notes.get(index); + note.incrementReviewCount(); + } + + //@@author ZiqiuZeng + public ArrayList getAll() { + return notes; + } + + //@@author ZiqiuZeng + public int getSize() { + return notes.size(); + } + + //@@author ZiqiuZeng + public ArrayList relevantInfo(String keyword) { + ArrayList relevantNotes = new ArrayList<>(); + for (Note note : notes) { + if (note.getText().contains(keyword)) { + relevantNotes.add(note); + } + } + return relevantNotes; + } + + //@@author ZiqiuZeng + public ArrayList relevantPriority(String priorityStr) { + NotePriority.Priority priority = NotePriority.Priority.valueOf(priorityStr); + ArrayList relevantNotes = new ArrayList<>(); + for (Note note : notes) { + if (note.getPriority() == priority) { + relevantNotes.add(note); + } + } + return relevantNotes; + } + + //@@author ZiqiuZeng + public ArrayList relevantMarked() { + ArrayList markedNotes = new ArrayList<>(); + for (Note note : notes) { + if (note.getIsDone()) { + markedNotes.add(note); + } + } + return markedNotes; + } + + //@@author ZiqiuZeng + public ArrayList relevantUnmarked() { + ArrayList unmarkedNotes = new ArrayList<>(); + for (Note note : notes) { + if (!note.getIsDone()) { + unmarkedNotes.add(note); + } + } + return unmarkedNotes; + } + + //@@author ZiqiuZeng + public void rankByReviewCount() { + notes.sort((note1, note2) -> Integer.compare(note2.getReviewCount(), note1.getReviewCount())); + } + + //@@author ZiqiuZeng + public void rankByPriority() { + Collections.sort(notes, new Comparator() { + @Override + public int compare(Note note1, Note note2) { + NotePriority.Priority priority1 = note1.getPriority(); + NotePriority.Priority priority2 = note2.getPriority(); + return priority2.compareTo(priority1); + } + }); + } + +} diff --git a/src/main/java/seedu/badmaths/storage/InvalidNotesFileHandler.java b/src/main/java/seedu/badmaths/storage/InvalidNotesFileHandler.java new file mode 100644 index 0000000000..f6ee3f8c7e --- /dev/null +++ b/src/main/java/seedu/badmaths/storage/InvalidNotesFileHandler.java @@ -0,0 +1,63 @@ +package seedu.badmaths.storage; + +import seedu.badmaths.note.Note; + +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Scanner; +import java.util.Timer; +import java.util.TimerTask; + +import static seedu.badmaths.storage.NotesFileParser.loadFile; + +public class InvalidNotesFileHandler { + /** + * Handles the response from user when an invalid format exception occurs while trying to load a notes file. + * Gives the user the option to reset the file and clears the note list, + * or exit the program if the user chooses not to reset the file. + * + * @param path the file path of the notes file + * @param notes the list of notes to clear if the user chooses to reset the file + */ + public static void responseHandler(String path, ArrayList notes) { + try{ + Scanner inputScanner = new Scanner(System.in); + System.out.println("Sorry, your notes file seems to be corrupted :("); + System.out.println("Do you want to reset the file? (y/n)"); + System.out.println(""); + String userInput = inputScanner.nextLine().trim().toLowerCase(); + if (userInput.equals("y")) { + // clear the file contents if the user confirms + PrintWriter writer = new PrintWriter(path); + writer.print(""); + writer.close(); + + // clear the note list if the user confirms + notes.clear(); + + System.out.println("File contents have rest successfully."); + System.out.println("You can continue to use the application"); + System.out.println("If you want to read Help Manual, " + + "please type 'Help' to learn what I can do for you."); + } else if (userInput.equals("n")){ + System.out.println("You choose not to rest the file."); + System.out.println("Please ensure your file status before using the application."); + System.out.println("The program will exit in 10 seconds. See you next time."); + Timer timer = new Timer(); + TimerTask exitTask = new TimerTask() { + @Override + public void run() { + System.exit(0); + } + }; + timer.schedule(exitTask, 10000); + } else { + System.out.println("Invalid input. Please enter 'y' or 'n'."); + loadFile(path); + } + } catch (FileNotFoundException eForInvalidFormatException) { + System.out.println(eForInvalidFormatException.getMessage()); + } + } +} diff --git a/src/main/java/seedu/badmaths/storage/NoteParser.java b/src/main/java/seedu/badmaths/storage/NoteParser.java new file mode 100644 index 0000000000..a781d51304 --- /dev/null +++ b/src/main/java/seedu/badmaths/storage/NoteParser.java @@ -0,0 +1,74 @@ +package seedu.badmaths.storage; + +import seedu.badmaths.InvalidFormatException; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import java.util.Set; + +public class NoteParser { + /** + * Parses a string representation of a note into a Note object. + * + * @param noteString the string representation of the note in the format "Priority \t Status \t Count \t Note" + * @return a Note object corresponding to the parsed string representation + * @throws InvalidFormatException if the input string is not in the expected format or contains invalid values + */ + public static Note parseNoteString(String noteString) throws InvalidFormatException{ + + //text format: Priority \\t Status \\t Count \\t Note + String[] noteInfo = noteString.split("\\t"); + + if (noteInfo.length != 4) { + throw new InvalidFormatException(); + } + + //priority + String priorityStr = noteInfo[0]; + Set validPriorities = Set.of("LOW", "MEDIUM", "HIGH"); + if (!validPriorities.contains(priorityStr)) { + //priorityStr is invalid, handle the error + throw new InvalidFormatException(); + } + NotePriority.Priority priority = NotePriority.Priority.valueOf(priorityStr); + + //note + String noteStr = noteInfo[3]; + + //count + String reviewCountStr = noteInfo[2]; + int reviewCount; + //reviewCountStr is invalid, handle the error + try { + reviewCount = Integer.parseInt(reviewCountStr); + } catch (NumberFormatException e) { + throw new InvalidFormatException(); + } + + //status + String isDoneStr = noteInfo[1]; + Set validIsDoneStatus = Set.of("Y", "N"); + if(!validIsDoneStatus.contains(isDoneStr)){ + //isDoneStr is invalid, handle the error + throw new InvalidFormatException(); + } + boolean isDone = isDoneStr.equals("Y"); + + /* + * update notes if the file is valid + */ + //update text, priority + Note note = new Note(noteStr, priority); + //update status + if(isDone) { + note.markAsDone(); + } else { + note.markAsNotDone(); + } + //update count + note.setReviewCount(reviewCount); + + //add note + return note; + } +} diff --git a/src/main/java/seedu/badmaths/storage/NotesFileCleaner.java b/src/main/java/seedu/badmaths/storage/NotesFileCleaner.java new file mode 100644 index 0000000000..a4016c47dc --- /dev/null +++ b/src/main/java/seedu/badmaths/storage/NotesFileCleaner.java @@ -0,0 +1,25 @@ +package seedu.badmaths.storage; + +import java.io.FileWriter; +import java.io.IOException; + +public class NotesFileCleaner { + /** + * Clears the contents of the file at the specified path. + * + * @param path the path of the file to be cleared + */ + public static void clearFile(String path) { + try { + FileWriter fileWriter = new FileWriter(path); + fileWriter.write(""); + fileWriter.close(); + System.out.println("File content cleared successfully!"); + } catch (IOException e) { + System.out.println("An error occurred while clearing the file content."); + e.printStackTrace(); + } + } +} + + diff --git a/src/main/java/seedu/badmaths/storage/NotesFileContentManager.java b/src/main/java/seedu/badmaths/storage/NotesFileContentManager.java new file mode 100644 index 0000000000..b1f5283e2c --- /dev/null +++ b/src/main/java/seedu/badmaths/storage/NotesFileContentManager.java @@ -0,0 +1,43 @@ +package seedu.badmaths.storage; + +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import java.util.ArrayList; + +public class NotesFileContentManager { + /** + * Returns a string representing the contents of a list of notes. + * + * @param notes the list of notes to be represented by a string + * @return a string representing the contents of the list of notes + */ + public static String fileContent(ArrayList notes) { + StringBuilder content = new StringBuilder(); + for(Note note : notes) { + //priority + NotePriority.Priority priority = note.getPriority(); + String priorityStr = priority.name(); + content.append(priorityStr).append("\t"); + //status + boolean isDone = note.getIsDone(); + String isDoneStatus = "N"; + if(isDone) { + isDoneStatus = "Y"; + } + content.append(isDoneStatus).append("\t"); + //count + int reviewCount = note.getReviewCount(); + String reviewCountStr = String.valueOf(reviewCount); + content.append(reviewCountStr).append("\t"); + //text + String noteText = note.getText(); + content.append(noteText); + //line separator + content.append(System.getProperty("line.separator")); + } + return content.toString(); + } +} + + diff --git a/src/main/java/seedu/badmaths/storage/NotesFileParser.java b/src/main/java/seedu/badmaths/storage/NotesFileParser.java new file mode 100644 index 0000000000..18ba7da57a --- /dev/null +++ b/src/main/java/seedu/badmaths/storage/NotesFileParser.java @@ -0,0 +1,38 @@ +package seedu.badmaths.storage; + +import seedu.badmaths.InvalidFormatException; +import seedu.badmaths.note.Note; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Scanner; + +import static seedu.badmaths.storage.NoteParser.parseNoteString; + +public class NotesFileParser { + /** + * Loads the contents of a notes file at the specified path + * and returns a list of Note objects representing the file's contents. + * + * @param path the path of the notes file to be loaded + * @return a list of Note objects representing the contents of the specified file + */ + public static ArrayList loadFile(String path) { + ArrayList notes = new ArrayList<>(); + try { + Scanner scanner = new Scanner(new File(path)); + String noteScanner; + while (scanner.hasNextLine()) { + noteScanner = scanner.nextLine(); + notes.add(parseNoteString(noteScanner)); + } + } catch (FileNotFoundException e) { + System.out.println(e.getMessage()); + } catch (InvalidFormatException e) { + InvalidNotesFileHandler.responseHandler(path, notes); + } + return notes; + } +} + diff --git a/src/main/java/seedu/badmaths/storage/NotesFileWriter.java b/src/main/java/seedu/badmaths/storage/NotesFileWriter.java new file mode 100644 index 0000000000..3293c11c05 --- /dev/null +++ b/src/main/java/seedu/badmaths/storage/NotesFileWriter.java @@ -0,0 +1,42 @@ +package seedu.badmaths.storage; + +import seedu.badmaths.note.Note; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; + +import static seedu.badmaths.storage.NotesFileContentManager.fileContent; + +public class NotesFileWriter { + /** + * Saves the list of notes to a file. + * + * @param path the path to the file to save + * @param notes the list of notes to save + */ + public static void saveFile(String path, ArrayList notes) { + File file = new File(path); + if (!file.exists()) { + System.out.println("File not exists, create it ..."); + if (!file.getParentFile().exists()) { + System.out.println("Directory not exists, create it ..."); + file.getParentFile().mkdirs(); + } + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + FileWriter fl = new FileWriter(path); + fl.write(fileContent(notes)); + fl.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} + diff --git a/src/main/java/seedu/badmaths/trigograph/GraphException.java b/src/main/java/seedu/badmaths/trigograph/GraphException.java new file mode 100644 index 0000000000..0d15653afd --- /dev/null +++ b/src/main/java/seedu/badmaths/trigograph/GraphException.java @@ -0,0 +1,5 @@ +package seedu.badmaths.trigograph; + +public class GraphException extends Exception{ + +} diff --git a/src/main/java/seedu/badmaths/trigograph/NegativeFrequencyException.java b/src/main/java/seedu/badmaths/trigograph/NegativeFrequencyException.java new file mode 100644 index 0000000000..592472b735 --- /dev/null +++ b/src/main/java/seedu/badmaths/trigograph/NegativeFrequencyException.java @@ -0,0 +1,4 @@ +package seedu.badmaths.trigograph; + +public class NegativeFrequencyException extends Exception{ +} diff --git a/src/main/java/seedu/badmaths/trigograph/TrigoGraph.java b/src/main/java/seedu/badmaths/trigograph/TrigoGraph.java new file mode 100644 index 0000000000..f564e77253 --- /dev/null +++ b/src/main/java/seedu/badmaths/trigograph/TrigoGraph.java @@ -0,0 +1,85 @@ +package seedu.badmaths.trigograph; + +import seedu.badmaths.IllegalTodoException; +import seedu.badmaths.ui.Ui; + +import java.awt.HeadlessException; + + +public class TrigoGraph { + private String trigoEqn; + private double amplitude; + private double frequency; + private double phase; + private double verticalShift; + private String trig; + + public TrigoGraph(String trigoEqn) { + this.trigoEqn = trigoEqn; + } + + public void startGraphAnalysis() throws IllegalTodoException { + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(trigoEqn); + if (trigoEqn.isEmpty()) { + throw new IllegalTodoException(); + } + try { + if (analyser.canStartAnalyser()) { + getGraphDetails(analyser); + printGraphDetails(); + TrigoGraphVisualiser visualiser = new TrigoGraphVisualiser(amplitude, phase, frequency, verticalShift, + trig); + visualiser.startVisualiser(); + } else { + throw new IllegalTodoException(); + } + } catch (IllegalTodoException e) { + throw new IllegalTodoException(); + } catch (HeadlessException e) { + assert true; + } + + } + + public void getGraphDetails(TrigoGraphAnalyser analyser) { + amplitude = analyser.getAmplitude(); + frequency = analyser.getFreq(); + phase = analyser.getPhase(); + verticalShift = analyser.getVerticalShift(); + trig = analyser.getTrigonometry(); + assert true : "Information retrieved."; + } + + + public void printGraphDetails() { + if (trig.equals("tan")) { + Ui.printTanHasNoAmplitude(); + } else { + Ui.printAmplitude(amplitude); + } + Ui.printFrequency(frequency); + Ui.printPhase(phase); + Ui.printVerticalShift(verticalShift); + assert true : "Information printed."; + } + + public double getAmplitude() { + return amplitude; + } + + public double getFrequency() { + return frequency; + } + + public double getPhase() { + return phase; + } + + public double getVerticalShift() { + return verticalShift; + } + + public String getTrig() { + return trig; + } +} diff --git a/src/main/java/seedu/badmaths/trigograph/TrigoGraphAnalyser.java b/src/main/java/seedu/badmaths/trigograph/TrigoGraphAnalyser.java new file mode 100644 index 0000000000..7d665834e9 --- /dev/null +++ b/src/main/java/seedu/badmaths/trigograph/TrigoGraphAnalyser.java @@ -0,0 +1,335 @@ +package seedu.badmaths.trigograph; + + +import seedu.badmaths.ui.Ui; + +import java.io.File; +import java.io.IOException; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +public class TrigoGraphAnalyser { + private static final boolean CAN_RUN_ANALYSER = true; + private static final boolean CANNOT_RUN_ANALYSER = false; + private static final int PLACEHOLDER_SIZE_WITH_NEG_PHASE = 3; + private static final int PLACEHOLDER_SIZE_WITH_POS_PHASE = 2; + private static final int PLACEHOLDER_SIZE_WITH_TRIGO_AND_VERTICAL_SHIFT = 2; + private static final int PLACEHOLDER_SIZE_WITH_AMPLITUDE_AND_EQN = 2; + private static final int INDEX_FOR_NEG_PHASE_WITH_NEG_FREQ = 2; + private static final int INDEX_FOR_NEG_PHASE_WITH_POS_FREQ = 1; + private static final int INDEX_FOR_FREQ_WITH_POS_PHASE = 0; + private static final int INDEX_FOR_POS_FREQ = 0; + private static final int INDEX_FOR_POS_PHASE = 1; + private static final int INDEX_FOR_NEG_FREQ = 1; + private static final int START_POS_OF_TRIG = 0; + private static final int END_POS_OF_TRIG = 3; + private static final int CORRECT_POS_OF_PHASE = 4; + private static final double ONE_HERTZ = 1.0; + private static final double ONE_AMPLITUDE = 1.0; + private static final double ZERO_PHASE = 0.0; + private static final double ZERO_VERTICAL_SHIFT = 0.0; + private static final double NEGATIVE_SIGN = -1.0; + private static final double ZERO_HERTZ = 0.0; + private static final int FIRST_INDEX_FOR_FREQ = 0; + private static final String STRING_NEGATIVE_SIGN = "-"; + private static final String STRING_POSITIVE_SIGN = "+"; + private static Logger logger = Logger.getLogger(TrigoGraphAnalyser.class.getName()); + private String trigoEqn; + private String trigonometry; + private double phase; + private double amplitude; + private double verticalShift; + private double freq; + + + public TrigoGraphAnalyser(String trigoEqn) { + this.trigoEqn = trigoEqn; + } + + public static void setUpLogger() { + LogManager.getLogManager().reset(); + logger.setLevel(Level.ALL); + try { + if (!new File("trigoGraphAnalyser.log").exists()) { + new File("trigoGraphAnalyser.log").createNewFile(); + } + FileHandler logFile = new FileHandler("trigoGraphAnalyser.log", true); + logFile.setLevel(Level.FINE); + logger.addHandler(logFile); + + } catch (IOException e) { + logger.log(Level.SEVERE, "File logger not working.", e); + } + } + + public String getTrig() { + return trigonometry; + } + + /** + * Main method that calls various methods to split the equation into Amplitude, Frequency, Phase Shift, + * and Vertical Shift. This method also catches the exceptions thrown and prints out the corresponding message to + * the user. + * + * @return true if equation entered is valid. + */ + public boolean canStartAnalyser() { + setUpLogger(); + try { + String[] amplitudeAndEqn = splitAmplitudeFromTrigoEqn(); + findAmplitude(amplitudeAndEqn); + String[] trigoAndVerticalShift; + // To handle the situation if equation starts with tan or 1*tan + if (isAmplitudeEqualsToOne(amplitudeAndEqn[0])) { + trigoAndVerticalShift = splitTrigoAndVerticalShift(trigoEqn); + } else { + trigoAndVerticalShift = splitTrigoAndVerticalShift(amplitudeAndEqn[1]); + } + findVerticalShift(trigoAndVerticalShift); + String trigo = trigoAndVerticalShift[0]; + splitTrigoIntoPhasors(trigo); + return CAN_RUN_ANALYSER; + } catch (NumberFormatException e) { + logger.log(Level.SEVERE, "NumberFormatException", e); + return CANNOT_RUN_ANALYSER; + } catch (GraphException e) { + logger.log(Level.SEVERE, "GraphException", e); + Ui.printNegativeAmplitudeEntered(); + return CANNOT_RUN_ANALYSER; + } catch (ArrayIndexOutOfBoundsException e) { + logger.log(Level.SEVERE, "ArrayIndexOutOfBounds", e); + return CANNOT_RUN_ANALYSER; + } catch (IllegalArgumentException e) { + logger.log(Level.SEVERE, "IllegalArguementException", e); + return CANNOT_RUN_ANALYSER; + } catch (NegativeFrequencyException e) { + Ui.printNegativeFrequencyEntered(); + return CANNOT_RUN_ANALYSER; + } catch (ZeroFrequencyException e) { + Ui.printZeroFrequencyEntered(); + return CANNOT_RUN_ANALYSER; + } + } + + /** + * Assigns an int to this amplitude. + * + * @param eqn contains the value of amplitude at index 0 and the remaining equation at index 1. + * @throws NumberFormatException if Double.parseDouble attempts to parse a non-numerical string such as "abc". + */ + public void findAmplitude(String[] eqn) throws NumberFormatException { + String[] trigoAndVerticalShift; + + if (isAmplitudeEqualsToOne(eqn[0])) { + amplitude = ONE_AMPLITUDE; + } else { + amplitude = Double.parseDouble(eqn[0]); + } + } + + private void testForSignOfAmplitude() throws GraphException { + if (trigoEqn.startsWith("-")) { + throw new GraphException(); + } + } + + public void testForMultipleAsterisk(String input) throws NumberFormatException { + if (input.startsWith("*")) { + throw new NumberFormatException(); + } + } + + public String[] splitAmplitudeFromTrigoEqn() throws GraphException, + NumberFormatException, ArrayIndexOutOfBoundsException { + testForSignOfAmplitude(); + String[] amplitudeAndEqn = trigoEqn.split("\\*", PLACEHOLDER_SIZE_WITH_AMPLITUDE_AND_EQN); + testForMultipleAsterisk(amplitudeAndEqn[1]); + return amplitudeAndEqn; + } + + public Double getAmplitude() { + return amplitude; + } + + public double getPhase() { + return phase; + } + + public double getVerticalShift() { + return verticalShift; + } + + public double getFreq() { + return freq; + } + + public String getTrigonometry() { + return trigonometry; + } + + private boolean isAmplitudeEqualsToOne(String input) { + if (input.startsWith("cos") || input.startsWith("sin") || input.startsWith("tan")) { + return true; + } + return false; + } + + + private boolean isVerticalShiftZero(String verticalShift) { + return verticalShift.isEmpty(); + } + + + private String[] splitTrigoAndVerticalShift(String eqn) { + + String[] trigoAndVerticalShift = eqn.split("\\)", PLACEHOLDER_SIZE_WITH_TRIGO_AND_VERTICAL_SHIFT); + return trigoAndVerticalShift; + } + + private void findVerticalShift(String[] trigoAndVerticalShift) { + if (isVerticalShiftZero(trigoAndVerticalShift[1])) { + verticalShift = ZERO_VERTICAL_SHIFT; + } else { + verticalShift = Double.parseDouble(trigoAndVerticalShift[1]); + } + } + + /** + * Remove the closing bracket in {@code trigo} to form a proper trigonometric equation containing frequency and + * phase. + * + * @param trigo is a trigo equation with amplitude and vertical shift removed + * @throws IllegalArgumentException + * @throws NegativeFrequencyException + * @throws ZeroFrequencyException + */ + public void splitTrigoIntoPhasors(String trigo) throws IllegalArgumentException, NegativeFrequencyException, + ZeroFrequencyException { + int startPosOfPhase = trigo.indexOf("(") + 1; + int endPosOfPhase = trigo.length(); + if (startPosOfPhase == CORRECT_POS_OF_PHASE) { + trigonometry = trigo.substring(START_POS_OF_TRIG, END_POS_OF_TRIG); + } else { + throw new IllegalArgumentException(); + } + + String phase = trigo.substring(startPosOfPhase, endPosOfPhase); + splitPhasorsIntoFreq(phase); + } + + public void findFreqForNoPhasors(String phasors) throws NegativeFrequencyException, ZeroFrequencyException { + phase = ZERO_PHASE; + boolean isFreqNegative = testForNegativeFreq(phasors); + findFreq(phasors, isFreqNegative); + } + + /* + * In the event that the phase is positive, this method will find the phase and frequency. + * @param phasors contain frequency and phase + * @throws NegativeFrequencyException + * @throws ZeroFrequencyException + */ + private void findFreqForPlus(String phasors) throws NegativeFrequencyException, ZeroFrequencyException { + String[] freqAndShift = phasors.split("\\+", PLACEHOLDER_SIZE_WITH_POS_PHASE); + findPhase(freqAndShift[INDEX_FOR_POS_PHASE], false); + boolean isFreqNegative = testForNegativeFreq(freqAndShift[INDEX_FOR_FREQ_WITH_POS_PHASE]); + findFreq(freqAndShift[INDEX_FOR_POS_FREQ], isFreqNegative); + } + + private void findFreqForMinus(String phasors) throws NegativeFrequencyException, ZeroFrequencyException { + /* + * If both phase and frequency are negative, empty string will be in index 0,freq will be in index 1, + * and phase will be in index 2 of freqAndShift. + * However, if only phase is negative, freq will be in index 0, phase will be in index 1, and empty string will + * in index 2. + */ + String[] freqAndShift = phasors.split(STRING_NEGATIVE_SIGN, PLACEHOLDER_SIZE_WITH_NEG_PHASE); + boolean isPhaseNegative = true; + // Find if freq is negative based on its index in freqAndShift as mentioned above + boolean isFreqNegative = testForNegativeFreq(freqAndShift); + if (isFreqNegative) { + findPhase(freqAndShift[INDEX_FOR_NEG_PHASE_WITH_NEG_FREQ], isPhaseNegative); + findFreq(freqAndShift[INDEX_FOR_NEG_FREQ], isFreqNegative); + } else { + findPhase(freqAndShift[INDEX_FOR_NEG_PHASE_WITH_POS_FREQ], isPhaseNegative); + findFreq(freqAndShift[INDEX_FOR_POS_FREQ], isFreqNegative); + } + } + + private void splitPhasorsIntoFreq(String phasors) throws NegativeFrequencyException, ZeroFrequencyException { + if (phasors.endsWith("x")) { + findFreqForNoPhasors(phasors); + } else if (phasors.contains(STRING_POSITIVE_SIGN)) { + findFreqForPlus(phasors); + } else { + findFreqForMinus(phasors); + } + } + + private boolean testForNegativeFreq(String[] freqAndShift) { + if (freqAndShift[INDEX_FOR_POS_FREQ].isEmpty()) { + return true; + } + return false; + } + + public boolean testForNegativeFreq(String freq) { + if (freq.startsWith(STRING_NEGATIVE_SIGN)) { + return true; + } + return false; + } + + public void findFreq(String freqWithX, boolean isFreqNeg) throws NumberFormatException, NegativeFrequencyException, + ZeroFrequencyException { + try { + if (isFreqNeg) { + throw new NegativeFrequencyException(); + } + String freqComponents; + if (freqWithX.equals("x")) { + freq = ONE_HERTZ / (2 * Math.PI); + } else { + /* + * freqWithX can have 1 or 2 "*", e.g. 5*pi*x or 5*x, simply split to get "5" will suffice as checks + * below will take "pi" into account, if any. + */ + int lastIndexForFreq = freqWithX.indexOf("*"); + freqComponents = freqWithX.substring(FIRST_INDEX_FOR_FREQ, lastIndexForFreq); + checkForZeroFreq(freqComponents); + if (trigoEqn.contains("pi")) { + freq = Double.parseDouble(freqComponents) / 2; + } else { + freq = Double.parseDouble(freqComponents) / (2 * Math.PI); + } + } + freq = Math.abs(freq); + + } catch (NumberFormatException e) { + throw new NumberFormatException(); + } + } + + public void checkForZeroFreq(String freqComponents) throws ZeroFrequencyException { + if (Double.parseDouble(freqComponents) == ZERO_HERTZ) { + throw new ZeroFrequencyException(); + } + } + + private void findPhase(String phasor, boolean isPhaseNegative) throws NumberFormatException { + try { + if (phasor.isEmpty()) { + phase = ZERO_PHASE; + } else if (isPhaseNegative) { + phase = Double.parseDouble(phasor) * (NEGATIVE_SIGN); + } else { + phase = Double.parseDouble(phasor); + } + } catch (NumberFormatException e) { + throw new NumberFormatException(); + } + } +} + diff --git a/src/main/java/seedu/badmaths/trigograph/TrigoGraphVisualiser.java b/src/main/java/seedu/badmaths/trigograph/TrigoGraphVisualiser.java new file mode 100644 index 0000000000..70a9f65195 --- /dev/null +++ b/src/main/java/seedu/badmaths/trigograph/TrigoGraphVisualiser.java @@ -0,0 +1,153 @@ +package seedu.badmaths.trigograph; + +import seedu.badmaths.IllegalTodoException; + + +import java.awt.HeadlessException; +import java.awt.Toolkit; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import javax.swing.JFrame; +import javax.swing.JPanel; + + +public class TrigoGraphVisualiser extends JPanel { + private static final double PRECISION_OF_GRAPH = 0.00001; + private static final double START_TIME = 0.0; + private static final int ZERO_X_COORDINATES = 0; + private static final int ZERO_Y_COORDINATES = 0; + private double amplitude; + private double phase; + private double freqInHz; + private double verticalShift; + private String trig; + private double xMin; + private double xMax; + private double yMin; + private double yMax; + + private boolean validState; + + public TrigoGraphVisualiser(double amplitude, double phase, double freqInHz, double verticalShift, String trig) + throws IllegalTodoException { + this.amplitude = amplitude; + this.trig = trig; + this.phase = phase; + this.freqInHz = freqInHz; + this.verticalShift = verticalShift; + xMin = (-2 * Math.PI) / freqInHz; + xMax = (2 * Math.PI) / freqInHz; + yMin = -(amplitude + Math.abs(verticalShift)) * 2; + yMax = (amplitude + Math.abs(verticalShift)) * 2; + validState = isTrigoValid(); + } + + public boolean isTrigoValid() throws IllegalTodoException { + if (trig.equals("tan") || trig.equals("cos") || trig.equals("sin")) { + return true; + } + throw new IllegalTodoException(); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + + int width = getWidth(); + int height = getHeight(); + + // Calculate scaling factors + double xScale = width / (xMax - xMin); + double yScale = height / (yMax - yMin); + + // Translate to make origin at the center + g.translate(width / 2, height / 2); + createXAxis(g, xScale, yScale); + createYAxis(g, xScale, yScale); + labelOrigin(g, xScale, yScale); + + if (trig.equals("sin")) { + drawSinCurve(g, xScale, yScale); + } + if (trig.equals("cos")) { + drawCosCurve(g, xScale, yScale); + } + if (trig.equals("tan")) { + drawTanCurve(g, xScale, yScale); + } + } + + public void labelOrigin(Graphics g, double xScale, double yScale) { + g.drawString("0", ZERO_X_COORDINATES, ZERO_Y_COORDINATES); + } + + public void createYAxis(Graphics g, double xScale, double yScale) { + g.setColor(Color.BLACK); + g.drawLine(ZERO_X_COORDINATES, (int) (yMin * yScale), ZERO_Y_COORDINATES, (int) (yMax * yScale)); + g.drawString("Amplitude", ZERO_X_COORDINATES, (int) ((yMin * yScale) * 0.9)); + } + + public void createXAxis(Graphics g, double xScale, double yScale) { + g.setColor(Color.BLACK); + g.drawLine((int) (xMin * xScale), ZERO_Y_COORDINATES, (int) (xMax * xScale), ZERO_Y_COORDINATES); + g.drawString("time", (int) ((xMax * xScale) - 0.2 * xMax * xScale), ZERO_Y_COORDINATES); + } + + public void drawSinCurve(Graphics g, double xScale, double yScale) { + g.setColor(Color.BLUE); + labelAmplitude(g, yScale); + for (double x = START_TIME; x <= xMax; x += PRECISION_OF_GRAPH) { + double y = amplitude * Math.sin(freqInHz * x + phase) + verticalShift; + int xPixel = (int) Math.round(x * xScale); + int yPixel = (int) Math.round(-y * yScale); + g.drawLine(xPixel - 1, yPixel, xPixel, yPixel); + } + } + + public void labelAmplitude(Graphics g, double yScale) { + g.drawString(String.valueOf(verticalShift + amplitude), ZERO_X_COORDINATES, + (int) (Math.round(-(verticalShift + amplitude) * yScale))); + g.drawString(String.valueOf(verticalShift - amplitude), ZERO_X_COORDINATES, + (int) (Math.round(-(verticalShift - amplitude) * yScale))); + } + + public void drawCosCurve(Graphics g, double xScale, double yScale) { + g.setColor(Color.RED); + labelAmplitude(g, yScale); + for (double x = START_TIME; x <= xMax; x += PRECISION_OF_GRAPH) { + double y = amplitude * Math.cos(freqInHz * x + phase) + verticalShift; + int xPixel = (int) Math.round(x * xScale); + int yPixel = (int) Math.round(-y * yScale); + g.drawLine(xPixel - 1, yPixel, xPixel, yPixel); + } + } + + + public void drawTanCurve(Graphics g, double xScale, double yScale) { + g.setColor(Color.BLACK); + for (double x = START_TIME; x <= xMax; x += PRECISION_OF_GRAPH) { + double y = amplitude * Math.tan(freqInHz * x + phase) + verticalShift; + int xPixel = (int) Math.round(x * xScale); + int yPixel = (int) Math.round(-y * yScale); + g.drawLine(xPixel - 1, yPixel, xPixel, yPixel); + } + } + + public boolean isValidState() { + return validState; + } + + public void startVisualiser() throws HeadlessException, IllegalTodoException { + JFrame frame = new JFrame("Trigonometric Graph"); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int screenWidth = screenSize.width; + int screenHeight = screenSize.height; + frame.setSize(screenWidth / 2, screenHeight / 2); + frame.setLocationRelativeTo(null); + frame.add(new TrigoGraphVisualiser(amplitude, phase, freqInHz, verticalShift, trig)); + frame.setVisible(true); + } + +} diff --git a/src/main/java/seedu/badmaths/trigograph/ZeroFrequencyException.java b/src/main/java/seedu/badmaths/trigograph/ZeroFrequencyException.java new file mode 100644 index 0000000000..2769b07487 --- /dev/null +++ b/src/main/java/seedu/badmaths/trigograph/ZeroFrequencyException.java @@ -0,0 +1,4 @@ +package seedu.badmaths.trigograph; + +public class ZeroFrequencyException extends Exception{ +} diff --git a/src/main/java/seedu/badmaths/ui/Ui.java b/src/main/java/seedu/badmaths/ui/Ui.java new file mode 100644 index 0000000000..ec5d335f12 --- /dev/null +++ b/src/main/java/seedu/badmaths/ui/Ui.java @@ -0,0 +1,199 @@ +package seedu.badmaths.ui; + +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import java.util.ArrayList; + +public class Ui { + + private static String logo = "\n" + + "____ _ __ __ _ _\n" + + "| _ \\ | | | \\/ | | | | |\n" + + "| |_) | __ _ __| | | \\ / | __ _| |_| |__ ___\n" + + "| _ < / _` |/ _` | | |\\/| |/ _` | __| '_ \\/ __|\n" + + "| |_) | (_| | (_| | | | | | (_| | |_| | | \\__ \\\n" + + "|____/ \\__,_|\\__,_| |_| |_|\\__,_|\\__|_| |_|___/"; + + + public static void printWelcomeMessage() { + System.out.println(logo + "\nYou can type 'Help' to learn what I can do for you :)"); + } + public static void printLogo(){ + System.out.println(logo); + } + public static void printTanHasNoAmplitude(){ + System.out.println("Psss... Tangent graph has no amplitude."); + } + public static void printNegativeFrequencyEntered(){ + System.out.println("Frequency cannot be negative."); + } + public static void printZeroFrequencyEntered(){ + System.out.println("Frequency cannot be zero."); + } + + public static void printIncorrectFormatEntered() { + System.out.println("Please enter the format as required."); + } + + public static void printNegativeAmplitudeEntered() { + System.out.println("Amplitude cannot be negative!"); + } + + public static void printAmplitude(double amplitude) { + System.out.println("This is the amplitude: " + amplitude); + } + + public static void printPhase(double phase) { + System.out.println("This is the phase: " + phase); + } + + public static void printVerticalShift(double verticalShift) { + System.out.println("This is the vertical shift: " + verticalShift); + } + + public static void printFrequency(Double freq) { + System.out.println("This is the freq (Hz): " + freq); + } + + //@@author WilsonLee2000 + public static void printInvalidNumberEntered() { + System.out.println("Input must be an integer!"); + } + + //@@author ZiqiuZeng + public static void printMark(String text) { + System.out.println("You have marked this note as done:"); + System.out.println(text); + } + + //@@author ZiqiuZeng + public static void printUnmark(String text) { + System.out.println("You have unmarked this note:"); + System.out.println(text); + } + + //@@author WilsonLee2000 + public static void printAddNote(String text, int size) { + System.out.println("You have added this note:"); + System.out.println(text); + System.out.println("Now you have " + size + " notes in the list."); + } + + //@@author WilsonLee2000 + public static void printDelete(String text, int size) { + System.out.println("You have removed this note:"); + System.out.println(text); + System.out.println("Now you have " + (size - 1) + " notes in the list."); + } + + //@@author WilsonLee2000 + public static void printNotes(ArrayList notes) { + if (notes.size() == 0) { + System.out.println("You have no notes yet. :("); + } else { + System.out.println("Here are the notes you have stored:"); + for (int i = 0; i < notes.size(); i++) { + System.out.println((i + 1) + ". " + notes.get(i).toString()); + } + System.out.println("Now you have " + notes.size() + " notes in the list."); + } + } + + //@@author WilsonLee2000 + public static void printSpecificNote(int index, ArrayList notes) { + if (index >= 0 && index < notes.size()) { + Note note = notes.get(index); + System.out.println("Here is the note you are looking for: "); + System.out.println((index + 1) + ": " + note.toString()); + } else { + System.out.println("Invalid note index"); + } + } + + //@@author ZiqiuZeng + public static void printFindNotes(ArrayList notes) { + if (notes.size() == 0) { + System.out.println("Sorry, no relevant results were found for this query. Please try other keywords."); + } else { + System.out.println("Here are the notes you are searching for:"); + for (int i = 0; i < notes.size(); i++) { + System.out.println((i + 1) + ". " + notes.get(i).toString()); + } + } + } + + //@@author ZiqiuZeng + public static void printPriority(int index, ArrayList notes) { + NotePriority.Priority priority = notes.get(index).getPriority(); + String priorityStr = priority.name(); + System.out.println("You have changed its priority to " + priorityStr); + System.out.println((index + 1) + ": " + notes.get(index).toString()); + } + + //@@author ZiqiuZeng + public static void printNotesByReviewCount(ArrayList notes) { + // Sort notes by review count in descending order + notes.sort((note1, note2) -> Integer.compare(note2.getReviewCount(), note1.getReviewCount())); + + // Print out notes by review count + System.out.println("Notes sorted by review count:"); + for (Note note : notes) { + System.out.println(note.getText() + " (review count: " + note.getReviewCount() + ")"); + } + } + + //@@author ZiqiuZeng + public static void printNotesByPriority(ArrayList notes) { + ArrayList highPriorityNotes = new ArrayList<>(); + ArrayList mediumPriorityNotes = new ArrayList<>(); + ArrayList lowPriorityNotes = new ArrayList<>(); + + for (Note note : notes) { + if (note.getPriority() == NotePriority.Priority.HIGH) { + highPriorityNotes.add(note); + } else if (note.getPriority() == NotePriority.Priority.MEDIUM) { + mediumPriorityNotes.add(note); + } else { + lowPriorityNotes.add(note); + } + } + + System.out.println("High priority notes:"); + for (Note note : highPriorityNotes) { + System.out.println(note.toString()); + } + + System.out.println("Medium priority notes:"); + for (Note note : mediumPriorityNotes) { + System.out.println(note.toString()); + } + + System.out.println("Low priority notes:"); + for (Note note : lowPriorityNotes) { + System.out.println(note.toString()); + } + } + + public static void printQuadraticFormatError() { + System.out.println("Please use the format as shown below:"); + System.out.println("ax^2 + bx + c");; + } + + public static void printQuadraticAnswer(ArrayList xStore, String vertexCoordinate, boolean isMinimum) { + if (xStore.get(0).isNaN() || xStore.get(1).isNaN()) { + System.out.println("x is imaginary."); + } else { + System.out.println("x1 = " + xStore.get(0) + " , x2 = " + xStore.get(1)); + if (isMinimum) { + System.out.println("There is a minimum point: " + vertexCoordinate); + } else { + System.out.println("There is a maximum point: " + vertexCoordinate); + } + } + } + + public static void printLineBreak() { + System.out.println("----------------------------------------------------------------------"); + } +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java deleted file mode 100644 index 5c74e68d59..0000000000 --- a/src/main/java/seedu/duke/Duke.java +++ /dev/null @@ -1,21 +0,0 @@ -package seedu.duke; - -import java.util.Scanner; - -public class Duke { - /** - * Main entry-point for the java.duke.Duke application. - */ - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - System.out.println("What is your name?"); - - Scanner in = new Scanner(System.in); - System.out.println("Hello " + in.nextLine()); - } -} diff --git a/src/main/resources/HelpManual.txt b/src/main/resources/HelpManual.txt new file mode 100644 index 0000000000..c40d4d6ebf --- /dev/null +++ b/src/main/resources/HelpManual.txt @@ -0,0 +1,30 @@ +------------------------------------------------------------------ +Hello! Welcome to the Help Manual for BadMaths! +------------------------------------------------------------------ +1. Type -> Graph [equation] <- to perform graph calculations +2. Type -> Matrix [equation] <- to perform matrix calculations +3. Type -> Store [any_string] <- to add notes +4. Type -> List <- to list all stored notes +5. Type -> List [index] <- to display a particular note +6. Type -> Delete [index] <- to delete a particular note +7. Type -> Clear <- to delete all stored notes +8. Type -> Mark [index] <- to mark a particular note as completed +9. Type -> Unmark [index] <- to unmark a particular note as incomplete +10. Type -> FindMark <- to display a list of all notes marked as completed +11. Type -> FindUnmark <- to display a list of all notes marked as incomplete +12. Type -> FindInfo <- to find items stored in Notes through searching for a keyword +13. Type -> [Priority] [index] <- to change the priority of a note +14. Type -> Rank Priority <- to display all notes of all priority rankings +15. Type -> Rank Review Count <- to display all notes ranked by review count +16. Type -> FindPrior [Priority] <- to display all notes of a certain priority +17. Type -> Quadratic [equation] <- to perform quadratic calculations +18. Type -> History <- to display a list of command history +19. Type -> Help <- to display content of Help Manual +20. Type -> Bye <- to exit program + +------------------------------------------------------------------- +Thank you for using BadMaths. We hope that BadMaths will be a useful study tool +in helping you to perform Mathematical Operations. +For more details, please visit our GitHub website [https://github.com/AY2223S2-CS2113-F10-2/tp]. +If you have any queries on BadMaths, please contact [wilsonleejunwei@u.nus.edu]. +------------------------------------------------------------------- diff --git a/src/test/java/seedu/badmaths/CommandHistoryTest.java b/src/test/java/seedu/badmaths/CommandHistoryTest.java new file mode 100644 index 0000000000..bdd25e6334 --- /dev/null +++ b/src/test/java/seedu/badmaths/CommandHistoryTest.java @@ -0,0 +1,32 @@ +//@@author WilsonLee2000 + +package seedu.badmaths; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.io.PrintStream; +import java.util.ArrayList; +import java.io.ByteArrayOutputStream; + +public class CommandHistoryTest { + + @Test + void checkStoreCommand() { + ArrayList historyCommand = new ArrayList<>(); + String inputCommand = "Hello"; + CommandHistory commandHistoryTest = new CommandHistory(historyCommand); + commandHistoryTest.storeCommand(inputCommand); + assertEquals(1, historyCommand.size()); + } + + @Test + void checkDisplayHistory() { + String correctDisplayOutput = ""; + ByteArrayOutputStream historyDisplayed = new ByteArrayOutputStream(); + ArrayList historyCommand = new ArrayList<>(); + CommandHistory commandHistoryTest = new CommandHistory(historyCommand); + commandHistoryTest.displayHistory(); + System.setOut(new PrintStream(historyDisplayed)); + String stringHistoryDisplayed = historyDisplayed.toString(); + assertEquals(correctDisplayOutput, stringHistoryDisplayed); + } +} diff --git a/src/test/java/seedu/badmaths/DeleteTest.java b/src/test/java/seedu/badmaths/DeleteTest.java new file mode 100644 index 0000000000..59a8215073 --- /dev/null +++ b/src/test/java/seedu/badmaths/DeleteTest.java @@ -0,0 +1,48 @@ +//@@author WilsonLee2000 + +package seedu.badmaths; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotesList; +import java.util.ArrayList; + +public class DeleteTest { + + @Test + void checkIsInvalidIndex() { + int index = 1; + String todo = "1"; + String itemOne = "One"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + notes.add(itemOne); + Delete deleteTest = new Delete(notes, todo); + boolean test = deleteTest.isInvalidIndex(index, notes); + assertEquals(true, test); + } + + @Test + void checkIsAnInt() { + String todo = "1"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + Delete deleteTest = new Delete(notes, todo); + boolean test = deleteTest.isAnInt(todo); + assertEquals(true, test); + } + + @Test + void checkDeleteNotes() { + String todo = "1"; + String itemOne = "One"; + String itemTwo = "Two"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + notes.add(itemOne); + notes.add(itemTwo); + Delete deleteTest = new Delete(notes, todo); + deleteTest.deleteNotes(); + assertEquals(1, notes.getSize()); + } +} diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/badmaths/DukeTest.java similarity index 88% rename from src/test/java/seedu/duke/DukeTest.java rename to src/test/java/seedu/badmaths/DukeTest.java index 2dda5fd651..c9fbfbf1b1 100644 --- a/src/test/java/seedu/duke/DukeTest.java +++ b/src/test/java/seedu/badmaths/DukeTest.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.badmaths; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/src/test/java/seedu/badmaths/IndexCheckerTest.java b/src/test/java/seedu/badmaths/IndexCheckerTest.java new file mode 100644 index 0000000000..249a304830 --- /dev/null +++ b/src/test/java/seedu/badmaths/IndexCheckerTest.java @@ -0,0 +1,28 @@ +package seedu.badmaths; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.commands.IndexChecker; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotesList; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class IndexCheckerTest { + @Test + public void testIsInvalidIndex() { + + ArrayList notes = new ArrayList<>(); + NotesList notesList = new NotesList(notes); + notesList.add("Note 1"); + notesList.add("Note 2"); + notesList.add("Note 3"); + + assertTrue(IndexChecker.isInvalidIndex(-1, notesList)); + assertFalse(IndexChecker.isInvalidIndex(2, notesList)); + assertFalse(IndexChecker.isInvalidIndex(0, notesList)); + assertFalse(IndexChecker.isInvalidIndex(1, notesList)); + } +} diff --git a/src/test/java/seedu/badmaths/IntegerCheckerTest.java b/src/test/java/seedu/badmaths/IntegerCheckerTest.java new file mode 100644 index 0000000000..00b1883e04 --- /dev/null +++ b/src/test/java/seedu/badmaths/IntegerCheckerTest.java @@ -0,0 +1,15 @@ +package seedu.badmaths; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.commands.IntegerChecker; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class IntegerCheckerTest { + @Test + public void testIsAnInt() { + assertTrue(IntegerChecker.isAnInt("1234567890")); + assertFalse(IntegerChecker.isAnInt("not a number")); + } +} diff --git a/src/test/java/seedu/badmaths/ListTest.java b/src/test/java/seedu/badmaths/ListTest.java new file mode 100644 index 0000000000..3210c7fbce --- /dev/null +++ b/src/test/java/seedu/badmaths/ListTest.java @@ -0,0 +1,60 @@ +//@@author WilsonLee2000 + +package seedu.badmaths; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.io.PrintStream; +import java.util.ArrayList; +import java.io.ByteArrayOutputStream; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotesList; + +public class ListTest { + + @Test + void checkIsInvalidIndex() { + int index = 1; + String todo = "1"; + String itemOne = "One"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + notes.add(itemOne); + List listTest = new List(notes, todo); + boolean test = listTest.isInvalidIndex(index, notes); + assertEquals(true, test); + } + + @Test + void checkIsAnInt() { + String todo = "1"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + List listTest = new List(notes, todo); + boolean test = listTest.isAnInt(todo); + assertEquals(true, test); + } + + @Test + void checkIsInvalidToDo() { + String todo = "82738232"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + List listTest = new List(notes, todo); + boolean test = listTest.isInvalidTodo(todo); + assertEquals(false, test); + } + + @Test + void testListNotes() { + ByteArrayOutputStream listDisplayed = new ByteArrayOutputStream(); + ArrayList notesArray = new ArrayList<>(); + String toDo = "index"; + NotesList notes = new NotesList(notesArray); + List listTest = new List(notes, toDo); + listTest.listNotes(); + String correctListOutput = ""; + System.setOut(new PrintStream(listDisplayed)); + String stringListDisplayed = listDisplayed.toString(); + assertEquals(correctListOutput, stringListDisplayed); + } +} diff --git a/src/test/java/seedu/badmaths/ParserTest.java b/src/test/java/seedu/badmaths/ParserTest.java new file mode 100644 index 0000000000..069b2c0b5e --- /dev/null +++ b/src/test/java/seedu/badmaths/ParserTest.java @@ -0,0 +1,39 @@ +package seedu.badmaths; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ParserTest { + + @Test + void getCommandShouldReturnCommand() { + String userInput = "Store store this"; + Parser parserTest = new Parser(userInput); + String commandTest = parserTest.getCommand(); + assertEquals(commandTest, "Store"); + } + + @Test + void getCommandShouldIgnoreTrailingSpaces() { + String userInput = " Store store this "; + Parser parserTest = new Parser(userInput); + String commandTest = parserTest.getCommand(); + assertEquals(commandTest, "Store"); + } + + @Test + void getToDoShouldReturnInvalidForSingleWordInput() { + String userInput = "Help"; + Parser parserTest = new Parser(userInput); + String toDoTest = parserTest.getToDo(); + assertEquals(toDoTest, "Invalid todo"); + } + @Test + void getToDoShouldIgnoreMultipleSpaces() { + String userInput = "Quadratic lol"; + Parser parserTest = new Parser(userInput); + String toDoTest = parserTest.getToDo(); + assertEquals(toDoTest, "lol"); + } +} diff --git a/src/test/java/seedu/badmaths/Quadratic/QuadraticParserTest.java b/src/test/java/seedu/badmaths/Quadratic/QuadraticParserTest.java new file mode 100644 index 0000000000..92517d3515 --- /dev/null +++ b/src/test/java/seedu/badmaths/Quadratic/QuadraticParserTest.java @@ -0,0 +1,77 @@ +package seedu.badmaths.Quadratic; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class QuadraticParserTest { + @Test + void findSignOfBShouldReturnSign() { + String toDo = "-2.5x^2 + 5x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + String sign = QuadraticParser.findSignOfB(); + assertEquals("+",sign); + } + + @Test + void findStringOfBShouldReturnB() { + String toDo = "-2.5x^2 + 5x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + String B = QuadraticParser.findStringOfB(); + assertEquals("5", B); + } + + @Test + void findSignOfCShouldReturnC() { + String toDo = "-2.5x^2 + 5x - 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + String sign = QuadraticParser.findSignOfC(); + assertEquals("-", sign); + } + + @Test + void findAShouldReturnA() { + String toDo = "-2.5x^2 + 5x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + double A = QuadraticParser.findA(); + assertEquals(-2.5, A); + } + @Test + void findStringOfCShouldReturnC() { + String toDo = "-2.5x^2 + 5x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + String C = QuadraticParser.findStringOfC(); + assertEquals("3", C); + } + + @Test + void findAIfOnlySignShouldReturnA() { + String toDo = "x^2 + 5.9x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + double A = QuadraticParser.findA(); + assertEquals(1, A); + } + @Test + void findBShouldReturnB() { + String toDo = "-2x^2 - 5.9x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + double B = QuadraticParser.findB(); + assertEquals(-5.9, B); + } + + @Test + void findBIfOnlySignShouldReturnB() { + String toDo = "-2x^2 - x + 3"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + double B = QuadraticParser.findB(); + assertEquals(-1, B); + } + + @Test + void findCShouldReturnC() { + String toDo = "-2x^2 + 5x + 3.0888"; + QuadraticParser quadraticTest = new QuadraticParser(toDo); + double C = QuadraticParser.findC(); + assertEquals(3.0888, C); + } +} diff --git a/src/test/java/seedu/badmaths/Quadratic/QuadraticTest.java b/src/test/java/seedu/badmaths/Quadratic/QuadraticTest.java new file mode 100644 index 0000000000..edfab97017 --- /dev/null +++ b/src/test/java/seedu/badmaths/Quadratic/QuadraticTest.java @@ -0,0 +1,32 @@ +package seedu.badmaths.Quadratic; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class QuadraticTest { + + @Test + void quadraticFormulaShouldReturnArrayOfX() { + String toDo = "-2x^2 + 5x + 3"; + Quadratic quadraticTest = new Quadratic(toDo); + ArrayList xStoreTest = new ArrayList<>(); + xStoreTest = quadraticTest.quadraticFormula(-2, 5, 3); + assertEquals(-0.5,xStoreTest.get(0)); + assertEquals(3.0,xStoreTest.get(1)); + } + + @Test + void minMaxPointFinderShouldReturnVertexCoordinate() { + String toDo = "-x^2 + x + 1"; + double A = -1; + double B = 1; + double C = 1; + Quadratic quadraticTest = new Quadratic(toDo); + String coordinate = quadraticTest.minMaxPointFinder(A, B, C); + assertEquals("(0.5, 1.25)", coordinate); + } + +} diff --git a/src/test/java/seedu/badmaths/StoreTest.java b/src/test/java/seedu/badmaths/StoreTest.java new file mode 100644 index 0000000000..a35d0ae188 --- /dev/null +++ b/src/test/java/seedu/badmaths/StoreTest.java @@ -0,0 +1,42 @@ +//@@author WilsonLee2000 + +package seedu.badmaths; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.ArrayList; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotesList; +import java.nio.file.Path; +import java.nio.file.Files; +import java.io.IOException; + +public class StoreTest { + + @Test + void checkIsInvalidToDo() throws IOException { + Path temporaryFile = Files.createTempFile("TempFile", ".txt"); + String contentsFile = "HIGH\tN\t0\tThis is a first test \nMEDIUM\tY\t2\tThis is a second test\n"; + Files.writeString(temporaryFile, contentsFile); + String todo = "82738232"; + ArrayList notesArray = new ArrayList<>(); + NotesList notes = new NotesList(notesArray); + Store storeTest = new Store(notes, todo); + boolean test = storeTest.isInvalidTodo(todo); + assertEquals(false, test); + Files.delete(temporaryFile); + } + + @Test + void storeValidInputCommand() throws IOException { + Path temporaryFile = Files.createTempFile("TempFile", ".txt"); + String contentsFile = "HIGH\tN\t0\tThis is a first test \nMEDIUM\tY\t2\tThis is a second test\n"; + Files.writeString(temporaryFile, contentsFile); + ArrayList notesArray = new ArrayList<>(); + String toDo = "index"; + NotesList notes = new NotesList(notesArray); + Store storeTest = new Store(notes, toDo); + storeTest.storeNotes(); + assertEquals(1, notes.getSize()); + Files.delete(temporaryFile); + } +} diff --git a/src/test/java/seedu/badmaths/help/HelpManualTest.java b/src/test/java/seedu/badmaths/help/HelpManualTest.java new file mode 100644 index 0000000000..0d1074e84b --- /dev/null +++ b/src/test/java/seedu/badmaths/help/HelpManualTest.java @@ -0,0 +1,45 @@ +package seedu.badmaths.help; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.HelpManual; + +import java.io.IOException; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; + +import java.util.logging.Logger; +import java.util.logging.LogManager; +import java.util.logging.Level; +import java.util.logging.Handler; + + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class HelpManualTest { + @Test + public void testReadHelpManual() throws IOException { + + final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + + Logger logger = Logger.getLogger(HelpManual.class.getName()); + LogManager.getLogManager().reset(); + logger.setLevel(Level.ALL); + Handler handler = new java.util.logging.StreamHandler(outContent, new java.util.logging.SimpleFormatter()); + handler.setLevel(Level.ALL); + logger.addHandler(handler); + + // Call the readHelpManual() method + HelpManual.readHelpManual(); + + // Check that the content is not null + assertNotNull(outContent.toString()); + + // Check if the output matches the expected output + String expectedOutput = new String(Files.readAllBytes(Paths.get("src/main/resources/HelpManual.txt"))); + assertEquals(expectedOutput, outContent.toString()); + } +} diff --git a/src/test/java/seedu/badmaths/matrix/CalculateTest.java b/src/test/java/seedu/badmaths/matrix/CalculateTest.java new file mode 100644 index 0000000000..dffd14706a --- /dev/null +++ b/src/test/java/seedu/badmaths/matrix/CalculateTest.java @@ -0,0 +1,93 @@ +package seedu.badmaths.matrix; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CalculateTest { + int[][] arr = new int[][]{ + {0, 1, 2}, + {3, 4, 5}, + {6, 7, 8}, + {9, 10, 11} + }; + Tensor2D tensor = new Tensor2D(arr); + + int[][] arrT = new int[][]{ + {0, 3, 6, 9}, + {1, 4, 7, 10}, + {2, 5, 8, 11} + }; + Tensor2D tensorT = new Tensor2D(arrT); + + int[][] dotResult = new int[][]{ + {0, 1, 4}, + {9, 16, 25}, + {36, 49, 64}, + {81, 100, 121} + }; + Tensor2D dotResultTensor = new Tensor2D(dotResult); + + int[][] mulResult = new int[][]{ + {5, 14, 23, 32}, + {14, 50, 86, 122}, + {23, 86, 149, 212}, + {32, 122, 212, 302} + }; + Tensor2D mulResultTensor = new Tensor2D(mulResult); + + int[][] addResult = new int[][]{ + {0, 2, 4}, + {6, 8, 10}, + {12, 14, 16}, + {18, 20, 22} + }; + Tensor2D addResultTensor = new Tensor2D(addResult); + + @Test + public void testShapeStringConversion() { + assertEquals("4 x 3", new Tensor2D(arr).shape().toString()); + } + + @Test + public void testMatrixTranspose(){ + for(int i=0; i notes = new ArrayList<>(); + Note note1 = new Note("This is a test note", NotePriority.Priority.HIGH); + Note note2 = new Note("This is another test note", NotePriority.Priority.MEDIUM); + note2.markAsDone(); + note2.incrementReviewCount(); + note2.incrementReviewCount(); + notes.add(note1); + notes.add(note2); + + // redirect System.in and System.out for testing + ByteArrayInputStream in = new ByteArrayInputStream("y\n".getBytes()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + System.setIn(in); + System.setOut(new PrintStream(out)); + + InvalidNotesFileHandler.responseHandler(tempFile.toString(), notes); + String expectedOutput = "Sorry, your notes file seems to be corrupted :(" + System.lineSeparator() + + "Do you want to reset the file? (y/n)" + System.lineSeparator() + System.lineSeparator() + + "File contents have rest successfully." + System.lineSeparator() + + "You can continue to use the application" + System.lineSeparator() + + "If you want to read Help Manual, please type 'Help' to learn what I can do for you." + + System.lineSeparator(); + assertEquals(expectedOutput, out.toString()); + + // verify that the file contents were cleared + assertEquals("", Files.readString(tempFile)); + + //verify that the ArrayList contents were cleared + assertEquals(0, notes.size()); + + // clean up + Files.delete(tempFile); + System.setIn(System.in); + System.setOut(System.out); + } + + @Test + public void testResponseHandlerExit() throws IOException { + + Path tempFile = Files.createTempFile("temp", ".txt"); + String fileContents = "HIGH\tN\t0\tThis is a test note\nMEDIUM\tY\t2\tThis is another test note\n"; + Files.writeString(tempFile, fileContents); + + // redirect System.in and System.out for testing + ByteArrayInputStream in = new ByteArrayInputStream("n\n".getBytes()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + System.setIn(in); + System.setOut(new PrintStream(out)); + + // create a temporary ArrayList + ArrayList notes = new ArrayList<>(); + Note note1 = new Note("This is a test note", NotePriority.Priority.HIGH); + Note note2 = new Note("This is another test note", NotePriority.Priority.MEDIUM); + note2.markAsDone(); + note2.incrementReviewCount(); + note2.incrementReviewCount(); + notes.add(note1); + notes.add(note2); + + // call the responseHandler method and verify the output + InvalidNotesFileHandler.responseHandler(tempFile.toString(), notes); + String expectedOutput = "Sorry, your notes file seems to be corrupted :(" + System.lineSeparator() + + "Do you want to reset the file? (y/n)" + System.lineSeparator() + System.lineSeparator() + + "You choose not to rest the file." + System.lineSeparator() + + "Please ensure your file status before using the application." + System.lineSeparator() + + "The program will exit in 10 seconds. See you next time." + System.lineSeparator(); + assertEquals(expectedOutput, out.toString()); + + // verify that the file contents were not cleared + assertEquals(fileContents, Files.readString(tempFile)); + + // clean up + Files.delete(tempFile); + System.setIn(System.in); + System.setOut(System.out); + } +} diff --git a/src/test/java/seedu/badmaths/storage/NoteParserTest.java b/src/test/java/seedu/badmaths/storage/NoteParserTest.java new file mode 100644 index 0000000000..e25847b0dc --- /dev/null +++ b/src/test/java/seedu/badmaths/storage/NoteParserTest.java @@ -0,0 +1,33 @@ +package seedu.badmaths.storage; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.InvalidFormatException; + +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class NoteParserTest { + @Test + public void testParseNoteString() throws InvalidFormatException { + String noteString1 = "HIGH\tY\t1\tThis is a test note."; + Note note1 = NoteParser.parseNoteString(noteString1); + assertTrue(note1.getIsDone()); + assertEquals(note1.getIsDoneIcon(), "Y"); + assertEquals(note1.getReviewCount(), 1); + assertEquals(note1.getPriority(), NotePriority.Priority.HIGH); + assertEquals(note1.getText(), "This is a test note."); + + String noteString2 = "MEDIUM\tN\t2\tThis is another test note."; + Note note2 = NoteParser.parseNoteString(noteString2); + assertFalse(note2.getIsDone()); + assertEquals(note2.getIsDoneIcon(), "N"); + assertEquals(note2.getReviewCount(), 2); + assertEquals(note2.getPriority(), NotePriority.Priority.MEDIUM); + assertEquals(note2.getText(), "This is another test note."); + } + +} diff --git a/src/test/java/seedu/badmaths/storage/NotesFileCleanerTest.java b/src/test/java/seedu/badmaths/storage/NotesFileCleanerTest.java new file mode 100644 index 0000000000..2d17563b59 --- /dev/null +++ b/src/test/java/seedu/badmaths/storage/NotesFileCleanerTest.java @@ -0,0 +1,39 @@ +package seedu.badmaths.storage; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class NotesFileCleanerTest { + + @Test + public void testClearFile() throws IOException{ + // set up test file and write some contents into it + Path tempFile = Files.createTempFile("temp", ".txt"); + String fileContents = "This is a test file."; + Files.writeString(tempFile, fileContents); + + // call clearFile method + NotesFileCleaner.clearFile(tempFile.toString()); + + // check that the file exists and is empty + File file = new File(tempFile.toString()); + assertTrue(file.exists()); + assertTrue(file.isFile()); + assertFalse(file.isDirectory()); + assertEquals(file.length(), 0); + + // clean up + Files.delete(tempFile); + System.setIn(System.in); + System.setOut(System.out); + } + +} diff --git a/src/test/java/seedu/badmaths/storage/NotesFileContentManagerTest.java b/src/test/java/seedu/badmaths/storage/NotesFileContentManagerTest.java new file mode 100644 index 0000000000..04585c172e --- /dev/null +++ b/src/test/java/seedu/badmaths/storage/NotesFileContentManagerTest.java @@ -0,0 +1,45 @@ +package seedu.badmaths.storage; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class NotesFileContentManagerTest { + + @Test + public void testFileContent() { + + //create three notes + Note note1 = new Note("Note 1", NotePriority.Priority.HIGH); + note1.markAsDone(); + note1.incrementReviewCount(); + + Note note2 = new Note("Note 2", NotePriority.Priority.MEDIUM); + + Note note3 = new Note("Note 3", NotePriority.Priority.LOW); + note3.markAsDone(); + note3.incrementReviewCount(); + note3.incrementReviewCount(); + + // add notes to an ArrayList + ArrayList notes = new ArrayList<>(); + notes.add(note1); + notes.add(note2); + notes.add(note3); + + // call the fileContent method and check the result + String expectedContent = "HIGH\tY\t1\tNote 1\n" + + "MEDIUM\tN\t0\tNote 2\n" + + "LOW\tY\t2\tNote 3\n"; + expectedContent = expectedContent.replace("\r\n", "\n").replace("\r", "\n"); + + String actualContent = NotesFileContentManager.fileContent(notes); + actualContent = actualContent.replace("\r\n", "\n").replace("\r", "\n"); + + assertEquals(expectedContent, actualContent); + } +} diff --git a/src/test/java/seedu/badmaths/storage/NotesFileParserTest.java b/src/test/java/seedu/badmaths/storage/NotesFileParserTest.java new file mode 100644 index 0000000000..acea0fbc76 --- /dev/null +++ b/src/test/java/seedu/badmaths/storage/NotesFileParserTest.java @@ -0,0 +1,40 @@ +package seedu.badmaths.storage; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class NotesFileParserTest { + + @Test + public void testLoadFile() { + + ArrayList expectedNotes = new ArrayList<>(); + expectedNotes.add(new Note("Note 1", NotePriority.Priority.HIGH)); + expectedNotes.add(new Note("Note 2", NotePriority.Priority.LOW)); + expectedNotes.add(new Note("Note 3", NotePriority.Priority.MEDIUM)); + expectedNotes.get(0).markAsDone(); + expectedNotes.get(0).setReviewCount(2); + expectedNotes.get(1).setReviewCount(1); + expectedNotes.get(2).setReviewCount(0); + expectedNotes.get(2).markAsDone(); + + String filePath = "src/test/resources/TestNotes.txt"; + + ArrayList actualNotes = NotesFileParser.loadFile(filePath); + assertEquals(expectedNotes.size(), actualNotes.size()); + + for (int i = 0; i < expectedNotes.size(); i++) { + Note expectedNote = expectedNotes.get(i); + Note actualNote = actualNotes.get(i); + assertEquals(expectedNote.getText(), actualNote.getText()); + assertEquals(expectedNote.getPriority(), actualNote.getPriority()); + assertEquals(expectedNote.getIsDone(), actualNote.getIsDone()); + assertEquals(expectedNote.getReviewCount(), actualNote.getReviewCount()); + } + } +} diff --git a/src/test/java/seedu/badmaths/storage/NotesFileWriterTest.java b/src/test/java/seedu/badmaths/storage/NotesFileWriterTest.java new file mode 100644 index 0000000000..fbefd04451 --- /dev/null +++ b/src/test/java/seedu/badmaths/storage/NotesFileWriterTest.java @@ -0,0 +1,65 @@ +package seedu.badmaths.storage; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.note.Note; +import seedu.badmaths.note.NotePriority; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class NotesFileWriterTest { + @Test + public void testSaveFile() throws IOException{ + + Path tempFile = Files.createTempFile("temp", ".txt"); + String fileContents = "This is a test file."; + Files.writeString(tempFile, fileContents); + + ArrayList testNotes = new ArrayList<>(); + + Note note1 = new Note("Note 1", NotePriority.Priority.HIGH); + note1.markAsDone(); + note1.incrementReviewCount(); + + Note note2 = new Note("Note 2", NotePriority.Priority.MEDIUM); + + Note note3 = new Note("Note 3", NotePriority.Priority.LOW); + note3.markAsDone(); + note3.incrementReviewCount(); + note3.incrementReviewCount(); + + testNotes.add(note1); + testNotes.add(note2); + testNotes.add(note3); + + // save the test notes to the test file + NotesFileWriter.saveFile(tempFile.toString(), testNotes); + + // check that the file exists + File file = new File(tempFile.toString()); + assertTrue(file.exists()); + + // check that the actual file content matches the expected string + String expectedContent = "HIGH\tY\t1\tNote 1\n" + + "MEDIUM\tN\t0\tNote 2\n" + + "LOW\tY\t2\tNote 3\n"; + + expectedContent = expectedContent.replace("\r\n", "\n").replace("\r", "\n"); + + String actualContent = ""; + actualContent = new String(Files.readAllBytes(file.toPath())); + actualContent = actualContent.replace("\r\n", "\n").replace("\r", "\n"); + assertEquals(expectedContent, actualContent); + + // clean up + Files.delete(tempFile); + System.setIn(System.in); + System.setOut(System.out); + } +} diff --git a/src/test/java/seedu/badmaths/trigograph/TrigoGraphAnalyserTest.java b/src/test/java/seedu/badmaths/trigograph/TrigoGraphAnalyserTest.java new file mode 100644 index 0000000000..4e1e507c70 --- /dev/null +++ b/src/test/java/seedu/badmaths/trigograph/TrigoGraphAnalyserTest.java @@ -0,0 +1,96 @@ +package seedu.badmaths.trigograph; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class TrigoGraphAnalyserTest { + @Test + void noAsteriskThrowsArrayIndexOutOfBoundsException() { + String eqn = "sin(x)"; + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(eqn); + assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + analyser.splitAmplitudeFromTrigoEqn(); + }); + assertEquals(false, analyser.canStartAnalyser()); + } + + @Test + void multipleAsteriskThrowsNumberFormatException() { + String eqn = "2**sin(4*x+1)-6"; + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(eqn); + assertThrows(NumberFormatException.class, () -> { + analyser.testForMultipleAsterisk("*sin(4*x+1)-6"); + }); + } + + @Test + void zeroVerticalShiftAndOneRadians() { + String eqn = "2*sin(1*x-1)"; + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(eqn); + analyser.canStartAnalyser(); + assertEquals(0.0, analyser.getVerticalShift()); + assertEquals(1.0 / (Math.PI * 2), analyser.getFreq()); + } + + @Test + void negativeAmplitudeShouldReturnIllegalArgumentException() { + String equation = "-2*sin(2*pi*x+1)+3"; + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(equation); + assertEquals(false, analyser.canStartAnalyser()); + assertThrows(GraphException.class, () -> { + analyser.splitAmplitudeFromTrigoEqn(); + }); + } + + @Test + void amplitudeOfOneShouldReturnOne() throws GraphException { + String equation = "sin(2*pi*x+1)+3"; + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(equation); + String[] input = analyser.splitAmplitudeFromTrigoEqn(); + analyser.findAmplitude(input); + assertEquals(1.0, analyser.getAmplitude()); + } + + @Test + void wrongFreqFormat_withMinus_expectsNegativeFrequencyException() { + String eqn = "2*cos(-*x+5)-2"; + TrigoGraphAnalyser test = new TrigoGraphAnalyser(eqn); + assertThrows(NegativeFrequencyException.class, () -> { + test.findFreq("-*x", test.testForNegativeFreq("-*x")); + }); + } + + @Test + void freqWithNoPhasorsExpectNoException() { + String freq = "5*x"; + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(freq); + assertDoesNotThrow(() -> { + analyser.findFreqForNoPhasors(freq); + }); + } + + @Test + void tanHasNoAmplitude() { + TrigoGraphAnalyser test = new TrigoGraphAnalyser("2*tan(2*x+5)-2"); + test.canStartAnalyser(); + assertEquals("tan", test.getTrig()); + } + + @Test + void zeroFrequencyExpectZeroFrequencyException() { + TrigoGraphAnalyser test = new TrigoGraphAnalyser("2*tan(0*x-1)+2"); + assertEquals(false, test.canStartAnalyser()); + assertThrows(ZeroFrequencyException.class, () -> { + test.findFreq("0*x", false); + }); + } + + @Test + void negativeFrequencyReturnsTrue() { + TrigoGraphAnalyser test = new TrigoGraphAnalyser("2*tan(0*x-1)+2"); + + } +} diff --git a/src/test/java/seedu/badmaths/trigograph/TrigoGraphTest.java b/src/test/java/seedu/badmaths/trigograph/TrigoGraphTest.java new file mode 100644 index 0000000000..ad1db48a5c --- /dev/null +++ b/src/test/java/seedu/badmaths/trigograph/TrigoGraphTest.java @@ -0,0 +1,104 @@ +package seedu.badmaths.trigograph; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.IllegalTodoException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class TrigoGraphTest { + @Test + void invalidEqnWithMultipleBrackets() { + String eqn = "2*((cos(2*x+1)))"; + TrigoGraph test = new TrigoGraph(eqn); + assertThrows(IllegalTodoException.class,()->{ + test.startGraphAnalysis(); + }); + } + @Test + void eqnWithTrigoAsSin(){ + String eqn = "2*sin(2*x-1)+1"; + TrigoGraph test = new TrigoGraph(eqn); + try { + test.startGraphAnalysis(); + assertEquals(2.0,test.getAmplitude()); + assertEquals(2/(2*Math.PI),test.getFrequency()); + assertEquals(-1.0,test.getPhase()); + assertEquals(1.0,test.getVerticalShift()); + assertEquals("sin",test.getTrig()); + } catch (IllegalTodoException e) { + System.out.println("JUnit test for integrateTestForTrigoGraph failed."); + } + } + + @Test + void emptyEqnExpectIllegalTodoException(){ + String eqn = ""; + TrigoGraph test = new TrigoGraph(eqn); + assertThrows(IllegalTodoException.class,()->{ + test.startGraphAnalysis(); + }); + } + + @Test + void integrateTestForTrigoGraph(){ + String eqn = "1*cos(8*x+8)-1"; + TrigoGraph test = new TrigoGraph(eqn); + try { + test.startGraphAnalysis(); + assertEquals(1.0,test.getAmplitude()); + assertEquals(8/(2*Math.PI),test.getFrequency()); + assertEquals(8.0,test.getPhase()); + assertEquals(-1.0,test.getVerticalShift()); + assertEquals("cos",test.getTrig()); + } catch (IllegalTodoException e) { + System.out.println("JUnit test for integrateTestForTrigoGraph failed."); + } + } + + @Test + void validEqn_withMinusFreq_expectCannotStartAnalyser() { + String eqn = "cos(-1*x-1)-1"; + TrigoGraphAnalyser test = new TrigoGraphAnalyser(eqn); + assertEquals(false, test.canStartAnalyser()); + } + + @Test + void validEqn_returnsCorrectDetails() { + String eqn = "2*tan(2*pi*x+1)-9"; + TrigoGraph graphTest = new TrigoGraph(eqn); + try { + graphTest.startGraphAnalysis(); + assertEquals(2.0, graphTest.getAmplitude()); + assertEquals("tan", graphTest.getTrig()); + assertEquals(1.0, graphTest.getFrequency()); + assertEquals(1.0, graphTest.getPhase()); + assertEquals(-9.0, graphTest.getVerticalShift()); + }catch (IllegalTodoException e){ + System.out.println("JUnit test for validEqn_returnsCorrectDetails failed."); + } + } + + @Test + void invalidEqn_withMultipleTrigo_expectCanStartAnalyserAsFalse() { + String eqn1 = "2*tan*tan(2*pi*x+1)-9"; + TrigoGraphAnalyser test = new TrigoGraphAnalyser(eqn1); + assertEquals(false, test.canStartAnalyser()); + + } + + @Test + void invalidEqn2_withMultipleTrigo_expectCanStartAnalyserAsFalse() { + String eqn2 = "2*tantan(2*pi*x+1)-9"; + TrigoGraphAnalyser test = new TrigoGraphAnalyser(eqn2); + assertEquals(false, test.canStartAnalyser()); + } + + @Test + void correctStatementsWithValidEqn() { + String eqn = "2*cos(2*pi*x+5)+1"; + TrigoGraph test = new TrigoGraph(eqn); + TrigoGraphAnalyser analyser = new TrigoGraphAnalyser(eqn); + assertEquals(true, analyser.canStartAnalyser()); + } +} diff --git a/src/test/java/seedu/badmaths/trigograph/TrigoGraphVisualiserTest.java b/src/test/java/seedu/badmaths/trigograph/TrigoGraphVisualiserTest.java new file mode 100644 index 0000000000..41ed98a7f4 --- /dev/null +++ b/src/test/java/seedu/badmaths/trigograph/TrigoGraphVisualiserTest.java @@ -0,0 +1,45 @@ +package seedu.badmaths.trigograph; + +import org.junit.jupiter.api.Test; +import seedu.badmaths.IllegalTodoException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class TrigoGraphVisualiserTest { + @Test + void eqnWithInvalidTrigoGivesInvalidState() { + try { + TrigoGraphVisualiser visualiser = new TrigoGraphVisualiser(1.0, 2.5, 1.67, + 9, "tann"); + visualiser.startVisualiser(); + assertThrows(IllegalTodoException.class, () -> { + visualiser.isValidState(); + }); + } catch (IllegalTodoException e) { + System.out.println("Wrong trigger."); + } + } + + @Test + void eqnWithValidTanGivesValidState() { + try { + TrigoGraphVisualiser visualiser_tan = new TrigoGraphVisualiser(1.0, 2.5, 1.67, + 9, "tan"); + assertEquals(true, visualiser_tan.isValidState()); + } catch (IllegalTodoException e) { + System.out.println("Wrong trigger."); + } + } + + @Test + void eqnWithValidSinGivesValidState() { + try { + TrigoGraphVisualiser visualiser_sin = new TrigoGraphVisualiser(1.0, 2.5, 1.67, + 9, "sin"); + assertEquals(true, visualiser_sin.isValidState()); + } catch (IllegalTodoException e) { + System.out.println("Wrong trigger."); + } + } +} diff --git a/src/test/resources/TestNotes.txt b/src/test/resources/TestNotes.txt new file mode 100644 index 0000000000..eddc3561c1 --- /dev/null +++ b/src/test/resources/TestNotes.txt @@ -0,0 +1,3 @@ +HIGH Y 2 Note 1 +LOW N 1 Note 2 +MEDIUM Y 0 Note 3 diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..3d040780c6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +1,10 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| -What is your name? -Hello James Gosling +____ _ __ __ _ _ +| _ \ | | | \/ | | | | | +| |_) | __ _ __| | | \ / | __ _| |_| |__ ___ +| _ < / _` |/ _` | | |\/| |/ _` | __| '_ \/ __| +| |_) | (_| | (_| | | | | | (_| | |_| | | \__ \ +|____/ \__,_|\__,_| |_| |_|\__,_|\__|_| |_|___/ +You can type 'Help' to learn what I can do for you :) +Goodbye! +---------------------------------------------------------------------- diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f95..09170083fc 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +1 @@ -James Gosling \ No newline at end of file +Bye diff --git a/trigo.JPG b/trigo.JPG new file mode 100644 index 0000000000..4e8b1992f0 Binary files /dev/null and b/trigo.JPG differ diff --git a/trigoGraphAnalyser.log b/trigoGraphAnalyser.log new file mode 100644 index 0000000000..54ca339ca4 --- /dev/null +++ b/trigoGraphAnalyser.log @@ -0,0 +1,44 @@ + + + + + 2023-04-10T04:51:24.737923200Z + 1681102284737 + 923200 + 0 + seedu.badmaths.trigograph.TrigoGraphAnalyser + SEVERE + seedu.badmaths.trigograph.TrigoGraphAnalyser + canStartAnalyser + 1 + ArrayIndexOutOfBounds + + java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 + + seedu.badmaths.trigograph.TrigoGraphAnalyser + findVerticalShift + 192 + + + seedu.badmaths.trigograph.TrigoGraphAnalyser + canStartAnalyser + 90 + + + seedu.badmaths.trigograph.TrigoGraph + startGraphAnalysis + 27 + + + seedu.badmaths.Command + executeCommand + 84 + + + seedu.badmaths.BadMaths + main + 79 + + + +