Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
yeekian committed Nov 11, 2024
2 parents d864dd0 + e5246a3 commit a084baf
Show file tree
Hide file tree
Showing 30 changed files with 162 additions and 64 deletions.
26 changes: 22 additions & 4 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
# Developer Guide

## Table of Contents
- [Acknowledgements](#acknowledgements)
- [Design](#design)
- [Architecture](#architecture)
- [Implementation](#implementation)
- [Add/Delete Student/Component Feature](#adddelete-studentcomponent-feature)
- [Find Student Feature](#find-student-feature)
- [Add/Delete Grade Feature](#adddelete-grade-feature)
- [Storage Load Feature](#storage-load-feature)
- [Appendix A: Product Scope](#appendix-a-product-scope)
- [Appendix B: User Stories](#appendix-b-user-stories)
- [Appendix C: Non-Functional Requirements](#appendix-c-non-functional-requirements)
- [Appendix D: Glossary](#appendix-d-glossary)
- [Appendix E: Instructions for Manual Testing](#appendix-e-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}
This project was inspired by our experiences using the Canvas learning management system. While Canvas serves large educational environments well, we envisioned a simpler, offline tool tailored for small classes that prioritizes essential features like grade tracking, student management, and assessment organization. Thus, TutorLink was born.

## Design & implementation
The design and feature set of TutorLink were developed from scratch, drawing inspiration from the need for a lightweight, offline solution for managing class assignments and reducing administrative overhead in small class environments. No code or external sources were directly referenced or reused in the development of TutorLink.
## Design

### Architecture

Expand Down Expand Up @@ -76,7 +94,7 @@ The following sequence diagrams depict the exact steps involved in the `AddStude

- `DeleteStudentCommand.execute(AppState appState, HashMap<String, String> arguments)`: Removes a student via the following
steps:
1. Retrieves and validates the matriculation number from arguments, throwing `IllegaValueException` exception
1. Retrieves and validates the matriculation number from arguments, throwing `IllegalValueException` exception
if matriculation number is null.
2. Searches for and deletes the student from `AppState`. Throws `StudentNotFoundException` if no student matching the matriculation number
is found.
Expand Down
17 changes: 13 additions & 4 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@
Your command terminal should look similar to the one below.

![tutorlink_startup.png](tutorlink_startup.png)

## Important Notes on Commands:
When inputting commands into `TutorLink`, kindly take note of the following:
- Commands with duplicate parameters will be rejected. *i.e* `add_student n/John Doe n/John Doe i/A1234567X`
- Parameters must be separated by at least one space character, otherwise the entire continuous string following a prefix
will be considered a single parameter. *i.e* `add_student i/A1234567X n/John Doei/A1234567X` will be intepreted as adding
a student with the name of `John Doei/A1234567X` and matric number `A1234567X`.
- Parameters can be supplied in any order. *i.e* `add_student n/John i/A1234567X` is the same as `add_student i/A1234567X n/John`
- **IMPORTANT**: Descriptions should **NOT** contain any separator tokens: `|` as this character is used for storage).
Including these may yield unpredictable results with the `Storage` component.
- Matric Number (`i/` argument) is case insensitive. Therefore, `A1234567X` is the same as `a1234567x`. Matric numbers
will be converted to uppercase for storage.
- Similarly, all other will be converted to lowercase for storage.
## Features

<div style="page-break-after: always;"></div>
Expand Down Expand Up @@ -179,10 +192,6 @@ respectively, located in the `[JAR file location]/data/` directory.

<div style="page-break-after: always;"></div>

## Notes:
- Matric Number (`i/` argument) is case insensitive. Therefore, `A1234567X` is the same as `a1234567x`. Matric numbers
will be converted to uppercase for storage.
- (coming soon) All other arguments are case insensitive and will be converted to lowercase for storage.
## FAQ

**Q**: How do I transfer my data to another computer?
Expand Down
Binary file modified docs/diagrams/AddComponentCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions docs/diagrams/AddComponentCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ C -> H : get("m/")
activate H
C <-- H : maxScoreNumber
deactivate H
destroy H


opt componentName or weightageNumber or maxScoreNumber is null
[<-- C : throw IllegalValueException
Expand Down Expand Up @@ -47,4 +49,6 @@ deactivate R

[<-- C : CommandResult
end
destroy R
destroy C
@enduml
Binary file modified docs/diagrams/AddGradeCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion docs/diagrams/AddGradeCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ deactivate R
deactivate C

end

destroy R
destroy C

@enduml
Binary file modified docs/diagrams/AddStudentCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/diagrams/AddStudentCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ deactivate R
[<-- C : CommandResult
deactivate C
end
destroy R
destroy C
@enduml
Binary file modified docs/diagrams/ArchitectureSequenceGrouped.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/diagrams/ArchitectureSequenceGrouped.puml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
@startuml!include Style.pumlparticipant ":TutorLink" as TL LOGIC_COLOR_5participant ":Ui" as UI LOGIC_COLOR_6participant ":Parser" as P LOGIC_COLOR_7participant ":XYZCommand" as C LOGIC_COLOR_3participant ":AppState" as A LOGIC_COLOR_2participant ":XYZStorage" as S LOGIC_COLOR_4[->TLactivate TLref over TL, UI : setuploop until exit command issued TL -> UI: getUserInput() activate UI TL <-- UI: line deactivate UI TL -> P : getCommand(line) activate P create C P -> C activate C P <-- C : XYZCommand deactivate C TL <-- P: XYZCommand deactivate P TL -> C : getArgumentPrefixes() activate C TL <-- C : argumentPrefixes deactivate C TL -> P: getArguments(argumentPrefixes, line) activate P TL <-- P : HashMap<String,String> deactivate P TL -> C : execute(appState, arguments) activate C ref over C, A : specific command execution alt command execution success TL <-- C : CommandResult deactivate C TL -> UI : displayResult() activate UI TL <-- UI deactivate UI else TutorLinkException TL -> UI : displayException(exception) activate UI TL <-- UI deactivate UI end TL -> TL : saveAllLists() activate TL TL -> S : save Student, Component and Grade Lists activate S TL <-- S deactivate S TL --> TL deactivate TLendTL->UI: displayGoodbyeMessage()activate UITL <-- UIdeactivate UI[<--TLdeactivate TL@enduml
@startuml!include Style.pumlparticipant ":TutorLink" as TL LOGIC_COLOR_5participant ":Ui" as UI LOGIC_COLOR_6participant ":Parser" as P LOGIC_COLOR_7participant ":XYZCommand" as C LOGIC_COLOR_3participant ":AppState" as A LOGIC_COLOR_2participant ":XYZStorage" as S LOGIC_COLOR_4[->TLactivate TLref over TL, UI : setuploop until exit command issued TL -> UI: getUserInput() activate UI TL <-- UI: line deactivate UI TL -> P : getCommand(line) activate P create C P -> C activate C P <-- C : XYZCommand deactivate C TL <-- P: XYZCommand deactivate P TL -> C : getArgumentPrefixes() activate C TL <-- C : argumentPrefixes deactivate C TL -> P: getArguments(argumentPrefixes, line) activate P TL <-- P : HashMap<String,String> deactivate P TL -> C : execute(appState, arguments) activate C ref over C, A : specific command execution alt command execution success TL <-- C : CommandResult deactivate C destroy C TL -> UI : displayResult() activate UI TL <-- UI deactivate UI else TutorLinkException TL -> UI : displayException(exception) activate UI TL <-- UI deactivate UI end TL -> TL : saveAllLists() activate TL TL -> S : save Student, Component and Grade Lists activate S TL <-- S deactivate S TL --> TL deactivate TLendTL->UI: displayGoodbyeMessage()activate UITL <-- UIdeactivate UI[<--TLdeactivate TL@enduml
Expand Down
Binary file modified docs/diagrams/DeleteComponentCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions docs/diagrams/DeleteComponentCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ C -> H : get("n/")
activate H
C <-- H : componentName
deactivate H
destroy H

opt componentName is null
[<-- C : throw IllegalValueException
Expand Down Expand Up @@ -43,4 +44,7 @@ deactivate R

[<-- C : CommandResult
end
destroy R
destroy C

@enduml
Binary file modified docs/diagrams/DeleteGradeCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion docs/diagrams/DeleteGradeCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ deactivate R
deactivate C

end

destroy R
destroy C

@enduml
Binary file modified docs/diagrams/DeleteStudentCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/diagrams/DeleteStudentCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ deactivate R
[<-- C : CommandResult
deactivate C
end
destroy R
destroy C
@enduml
Binary file modified docs/diagrams/FindStudentCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/diagrams/FindStudentCommand.puml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ deactivate R
[<-- C : CommandResult
deactivate C
end
destroy R
destroy C
@enduml
4 changes: 4 additions & 0 deletions src/main/java/tutorlink/command/ListComponentCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class ListComponentCommand extends Command {

/** The command word used to trigger this command. */
public static final String COMMAND_WORD = "list_component";
private static final String MESSAGE_NO_COMPONENTS = "No components have been recorded yet.";

/**
* Executes the command to list all components.
Expand All @@ -23,6 +24,9 @@ public class ListComponentCommand extends Command {
*/
@Override
public CommandResult execute(AppState appState, HashMap<String, String> parameters) {
if(appState.components.size() <= 0) {
return new CommandResult(MESSAGE_NO_COMPONENTS);
}
return new CommandResult(appState.components.toString());
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/tutorlink/command/ListStudentCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public class ListStudentCommand extends Command {

public static final String COMMAND_WORD = "list_student";
private static final String MESSAGE_NO_STUDENTS = "No students have been recorded yet.";

/**
* Executes the command to list all students, retrieving the student list from the application state.
Expand All @@ -22,6 +23,9 @@ public class ListStudentCommand extends Command {
*/
@Override
public CommandResult execute(AppState appState, HashMap<String, String> hashMap) {
if(appState.students.size() <= 0) {
return new CommandResult(MESSAGE_NO_STUDENTS);
}
return new CommandResult(appState.students.toString());
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/tutorlink/commons/Commons.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ public class Commons {

//Input Validation
public static final String MATRIC_NUMBER_REGEX = "A\\d{7}[A-Z]";
public static final String ERROR_ILLEGAL_MATRIC_NUMBER = "Error! Ensure matric " +
"number is of the form A\\d{7}[A-Z] (case insensitive)";
public static final String ERROR_ILLEGAL_MATRIC_NUMBER = "Error! Matric Number should start with \"A\", " +
"followed by 7 digits, and end with an uppercase letter (e.g., A1234567X)";
//Student
public static final String ADD_STUDENT_SUCCESS = "Student %s (%s) added successfully!";
public static final String ERROR_DUPLICATE_STUDENT =
Expand All @@ -23,7 +23,7 @@ public class Commons {
public static final String DELETE_GRADE_SUCCESS = "Grade: Component %s for student %s successfully deleted";
public static final String ADD_GRADE_SUCCESS = "Score of %s added successfully to %s for %s!";
public static final String ERROR_INVALID_SCORE =
"Error! Score must be double that is more than or equal to 0, and not exceed the max score!";
"Error! Score must be a numerical value and be between 0 and the max score of the component!";

//@@author TrungBui32
//Component
Expand All @@ -39,7 +39,7 @@ public class Commons {
public static final String ERROR_INVALID_MAX_SCORE =
"Error! Max Score must be double that is more than or equal to 0!";
//@@author RCPilot1604
public static final String ERROR_INVALID_TOTAL_WEIGHTING = "Error! Total weighting must add up to 100%%.\n" +
public static final String ERROR_INVALID_TOTAL_WEIGHTING = "Error! Total weighting must not exceed 100%%.\n" +
"Current weighting (after addition): %s%%";

//Invalid
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/tutorlink/parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
import tutorlink.command.AddGradeCommand;
import tutorlink.command.AddComponentCommand;
import tutorlink.command.UpdateComponentCommand;
import tutorlink.exceptions.IllegalValueException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -26,6 +29,7 @@
*/
public class Parser {
private static final Logger LOGGER = Logger.getLogger(Parser.class.getName());
private static final String ERROR_PARSER_MULTIPLE_PREFIX = "Duplicate prefix detected: ";

/**
* Extracts the command word from the given input by splitting the input
Expand Down Expand Up @@ -101,7 +105,7 @@ public Command getCommand(String line) {
* @param line The user input containing command arguments.
* @return A {@code HashMap} where keys are prefixes (e.g., "n/", "i/") and values are the corresponding arguments.
*/
public HashMap<String, String> getArguments(String[] argumentPrefixes, String line) {
public HashMap<String, String> getArguments(String[] argumentPrefixes, String line) throws IllegalValueException {
HashMap<String, String> arguments = new HashMap<>();

if (argumentPrefixes == null) {
Expand All @@ -120,11 +124,16 @@ public HashMap<String, String> getArguments(String[] argumentPrefixes, String li
String regex = regexBuilder.toString();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(line);

// Set to track prefixes we've already encountered
Set<String> seenPrefixes = new HashSet<>();
// Iterate through all found tags and arguments
while (matcher.find()) {
String tag = matcher.group(1); // Group 1 is the tag (e.g., n/, i/, etc.)
String argument = matcher.group(2).trim(); // Group 2 is the argument after the tag
if (seenPrefixes.contains(tag)) {
throw new IllegalValueException(ERROR_PARSER_MULTIPLE_PREFIX + tag);
}
seenPrefixes.add(tag);
arguments.put(tag, argument); // Store the tag and argument
}

Expand Down
Loading

0 comments on commit a084baf

Please sign in to comment.