Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CS2113-W13-4] TutorLink #13

Open
wants to merge 795 commits into
base: master
Choose a base branch
from

Conversation

RCPilot1604
Copy link

NUS professors juggle admin tasks like tracking attendance and managing assignments, which detracts from their time for lesson preparation. Our app simplifies these processes by automating routine tasks and presenting concise, essential information, freeing up valuable time and enhancing their focus on teaching.

Copy link

@Mahesh1772 Mahesh1772 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job overall! The code is solid, and the functionality is well-implemented. I only had a few minor recommendations, mainly around Javadocs, using constants and naming, but nothing that detracts from the quality of the work. Thanks for the effort and attention to detail here!

Comment on lines 40 to 78
private GradeList addGradeForTest(Parser parser, AppState appState, String componentName) {
//Create student
String line = "add_student i/A1234567X n/John Doe";
Command addStudentCommand = new AddStudentCommand();
String[] argumentPrefixes = addStudentCommand.getArgumentPrefixes();
HashMap<String, String> arguments = parser.getArguments(argumentPrefixes, line);
CommandResult result = addStudentCommand.execute(appState, arguments);
assertNotNull(result);
assertEquals("Student John Doe (A1234567X) added successfully!", result.toString());
assertEquals(appState.students.getStudentArrayList().size(), 1);

//Create component
String examName = componentName;
double examMaxScore = 100.0;
double examWeight = 50.0;
Exam exam = new Exam(examName,examMaxScore, examWeight);

appState.components.addComponent(exam);

//Add grade
HashMap<String, String> gradeArguments = new HashMap<>();

String matricNumber = "A1234567X";
String componentDescription = componentName;
String scoreNumber = "75.0";
gradeArguments.put("i/",matricNumber);
gradeArguments.put("c/", componentDescription);
gradeArguments.put("s/", scoreNumber);

Command addGradeCommand = new AddGradeCommand();
CommandResult gradeResult = addGradeCommand.execute(appState, gradeArguments);

//Test grade added
assertNotNull(gradeResult);
assertEquals(String.format(successMessage, scoreNumber, componentDescription, matricNumber),
gradeResult.toString());

return appState.grades;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addGradeForTest() is too long (>30 LOC) and doing multiple things, violating the "Avoid Long Methods" and the "Single Responsibility" principle. Consider breaking it down into smaller helper methods.

Comment on lines 53 to 54
double examMaxScore = 100.0;
double examWeight = 50.0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider converting magic numbers and strings to constants, to increase maintainability.


private GradeList addGradeForTest(Parser parser, AppState appState, String componentName) {
//Create student
String line = "add_student i/A1234567X n/John Doe";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable names could be more descriptive

HashMap<String, String> arguments = parser.getArguments(argumentPrefixes, line);
CommandResult result = addStudentCommand.execute(appState, arguments);
assertNotNull(result);
assertEquals("Student John Doe (A1234567X) added successfully!", result.toString());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The success string could be added to the UI class

}

@Test
void execute_matric_one() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test method names don't follow the recommended format featureUnderTest_testScenario_expectedBehavior(). Consider renaming.

Comment on lines 24 to 26
comp1 = new Assignment("Homework 1", 30, 0.1);
comp2 = new Assignment("Homework 2", 30, 0.1);
comp3 = new Exam("Finals", 100, 0.5);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using more descriptive variable names

}

@Test
void toString_test() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure to follow the format featureUnderTest_testScenario_expectedBehavior() like you have with others

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class ComponentListTest {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding Javadocs

Comment on lines 73 to 99
public double calculateStudentGPA(String matricNumber, ComponentList componentList)
throws IncompleteGradesException {
ArrayList<Grade> studentGrades = gradeArrayList
.stream()
.filter(grade -> grade.getStudent().getMatricNumber().equals(matricNumber.toUpperCase()))
.collect(Collectors.toCollection(ArrayList::new));

ArrayList<Component> allComponents = componentList.findAllComponents();

if (studentGrades.isEmpty()) {
throw new StudentNotFoundException("No grades found for student: " + matricNumber);
}

boolean hasAllComponents = allComponents.stream()
.allMatch(component -> studentGrades.stream()
.anyMatch(grade -> grade.getComponent().equals(component)));

if (!hasAllComponents) {
throw new IncompleteGradesException(
"Cannot calculate GPA: Student " + matricNumber + " is missing grades for some components");
}

return studentGrades
.stream()
.mapToDouble(grade -> grade.getScore() * grade.getComponent().getWeight())
.sum();
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method is doing too many things (SLAP violation) - consider breaking into smaller methods. Magic number 0.07 in tax calculation could be a constant

Comment on lines 30 to 40
public boolean deleteGrade(String matricNumber, String componentDescription) {
matricNumber = matricNumber.toUpperCase();
componentDescription = componentDescription.toLowerCase();
for (Grade grade : gradeArrayList) {
if (grade.getStudent().getMatricNumber().equals(matricNumber)
&& grade.getComponent().getName().equals(componentDescription)) {
return gradeArrayList.remove(grade);
}
}
return false;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using early return pattern to reduce nesting

Copy link

@yakultbottle yakultbottle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, only minor questions

@@ -2,37 +2,189 @@

## Acknowledgements

{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well}
{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the
original source as well}

## Design & implementation

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this header Design & implementation be removed, since there is a separate Implementation header below?

Comment on lines 116 to 119
The following sequence diagrams depict the exact steps involved in the `AddStudentCommand`:

![AddStudentCommand.png](diagrams/AddStudentCommand.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Should there be a dotted line indicating the main program calling this function?

Comment on lines 96 to 99
All commands follow the sequence as described in the diagram below:

![ArchitectureSequenceGrouped.png](diagrams%2FArchitectureSequenceGrouped.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Could this constructor be omitted from this diagram, since it is not necessary to demonstrate command flow sequence?

Comment on lines 178 to 180

![GradeStorage.png](diagrams/GradeStorage.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could all the instantiations be moved into a separate diagram?

Copy link

@wongwh2002 wongwh2002 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other than the comments, lgtm!


{Describe the value proposition: what problem does it solve?}
- At app launch, TutorLink initializes components (<code>Parser</code>, <code>Ui</code>, <code>Storage</code>, <code>
AppState</code>).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting issue here


## Product scope
### Target user profile
![Architecture.png](diagrams/Architecture.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

confusing diagram, do not understand what the arrows and lines are trying to say, maybe add a legend of what each line


All commands follow the sequence as described in the diagram below:

![ArchitectureSequenceGrouped.png](diagrams%2FArchitectureSequenceGrouped.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the displayException have a return to standardise?

All commands follow the sequence as described in the diagram below:

![ArchitectureSequenceGrouped.png](diagrams%2FArchitectureSequenceGrouped.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you use alt for exception? maybe use alt [success] and [failure]?
would opt [success] be better


All commands follow the sequence as described in the diagram below:

![ArchitectureSequenceGrouped.png](diagrams%2FArchitectureSequenceGrouped.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you concise the alt [success] sequence? the (new StudentComponent, ComponentStorage, GradeStorage) and the rest is a bit messy/confusing


Likewise, the sequence diagram for `DeleteStudentCommand` is as follows:

![DeleteStudentCommand.png](diagrams%2FDeleteStudentCommand.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you have a lifeline for where "main"/ or something calls DeleteStudentCommand for better readability


The sequence diagram of the DeleteGradeCommand is shown below.

![AddGradeCommand.png](diagrams%2FAddGradeCommand.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should AddStudentCommand have a X at the end of the lifeline of an object to show its deletion

Comment on lines 181 to 190
1. TutorLink constructs a new `GradeStorage`.
2. TutorLink calls `loadGradeList`.
3. `GradeStorage` creates a new `ArrayList` of `Grade`s.
4. `GradeStorage` creates a new `Scanner` with the path to the file.
5. While there are next lines in the data file:
- `Scanner` returns the current file line as a String and moves to the next file line.
- `GradeStorage` calls its `getGradeFromFileLine` method with the file line.
- If the file line references a valid `Component` and a valid `Student`, a `Grade` is returned and added to the `ArrayList`.
- If not (e.g. if data file was corrupted), the file line is simply ignored, and the loop continues to the next iteration.
6. The `ArrayList` of `Grade`s is returned to TutorLink.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be more concise instead of going through your entire program/algorithm

@@ -2,37 +2,189 @@

## Acknowledgements

{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well}
{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you include a class diagram

@@ -2,37 +2,189 @@

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm in general!

Copy link

@sarahchow03 sarahchow03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the diagrams are well-documented and rigorous! I liked how the classes were colour-coded and standard across all diagrams, and that there was efficient use of reference frames in your team's DG. Good job!

Copy link

@sarahchow03 sarahchow03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be some standardization for the function calls in this diagram, specifically for displayResult to be displayResult()?

Copy link

@sarahchow03 sarahchow03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the lifeline for Scanner terminate after X, as it indicates the end of the lifeline?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: In the alt frame of this diagram, one or two words to indicate what was successful will be good!

Copy link

@sarahchow03 sarahchow03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although including activation bars are not compulsory, with reference to the sequence diagram for AddGradeCommand and DeleteGradeCommand, should the activation bar for :DeleteStudentCommand be included to ensure uniformity across your team's diagrams?

Copy link

@sarahchow03 sarahchow03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to a previous comment, the activation bar for :FindStudentCommand could be included to ensure uniformity across your team's diagrams!

Copy link

@sarahchow03 sarahchow03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the alt frame of this diagram, the second condition has not been labelled. This could be fixed by adding a [else].

Copy link

@sarahchow03 sarahchow03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to a previous comment, should the activation bar for :AddComponentCommand be included to ensure uniformity across your team's diagrams?

RCPilot1604 and others added 30 commits November 12, 2024 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants