From 63ce703ae75c53e5f3cb912944efa0d0bca83b7e Mon Sep 17 00:00:00 2001 From: Sean Yap Date: Tue, 2 Apr 2019 03:46:04 +0800 Subject: [PATCH] v1.3 (#146) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Merge (#21) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Resolve merge conflicts * Merge (#24) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Merge (#23) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Add KeyStore to store encryption key * change some ab3 references to planmysem * export location only if location exists * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update User Guide and Dev Guide for encryption (#114) * merge upstream (#6) * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update docs * Fix checkstyle * Merge codacy * Resolve conflicts * resolve whitesapce * Merge (#27) * Resolve checkstyle errors * Update use cases in developer guide * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Add KeyStore to store encryption key * change some ab3 references to planmysem * export location only if location exists * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update User Guide and Dev Guide for encryption (#114) * merge upstream (#6) * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update docs * Add tests for Add, Edit and Delete commands and optimise code (#115) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * Add tests for Add, Edit and Delete commands and optimise code * Fix checkstyle error * Move Semester generation code (#116) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Moved Semester generation code * Planner: remove unused imports * Semester: undo minor change * Testing (#29) * Update dev guide * Merge (#28) * Resolve checkstyle errors * Update use cases in developer guide * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Add KeyStore to store encryption key * change some ab3 references to planmysem * export location only if location exists * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update User Guide and Dev Guide for encryption (#114) * merge upstream (#6) * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update docs * Add tests for Add, Edit and Delete commands and optimise code (#115) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * Add tests for Add, Edit and Delete commands and optimise code * Fix checkstyle error * Move Semester generation code (#116) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Moved Semester generation code * Planner: remove unused imports * Semester: undo minor change * Update Dev Guide for initialization of Semester (#117) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Moved Semester generation code * Planner: remove unused imports * Semester: undo minor change * DeveloperGuide: Update documentation on initialization of Semester * Update * Merge (#30) * Update entire project to follow better software engineering practices * Resolve merge conflict * Merge (#32) * Resolve checkstyle errors * Update use cases in developer guide * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Add KeyStore to store encryption key * change some ab3 references to planmysem * export location only if location exists * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update User Guide and Dev Guide for encryption (#114) * merge upstream (#6) * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags (#111) * Merge (#18) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Resolve conflicts * Merge (#19) * Resolve checkstyle errors * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide (#101) * Merge (#17) * FIx Bug in FindCommand (#97) Fix Bug in FindCommand * Update User Guide documentation (#98) * Update User Guide documentation (#99) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update UserGuide.adoc (#100) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Update User Guide * Add config file for Reposense * Add config file for Reposense (#102) * Move config.json to _reposense folder * Move config.json to _reposense folder (#103) * Edit config file for reposense * Update User Guide (#105) * Update use cases in developer guide * edit user guide * add encryption key skeleton * user guide edits * Update User Guide (#106) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Update README.adoc and UserGuide.adoc: change table layouts (#110) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update User Guide (#108) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Enhance list and find functionality to include tags * Update docs * Add tests for Add, Edit and Delete commands and optimise code (#115) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * Add tests for Add, Edit and Delete commands and optimise code * Fix checkstyle error * Move Semester generation code (#116) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Moved Semester generation code * Planner: remove unused imports * Semester: undo minor change * Update Dev Guide for initialization of Semester (#117) * Planner: Initialize weekType for each Day * Planner: Fix Codacy issue * Planner: Update code for initialisation of semester * Planner: Fix Codacy and checkstyle issues * Planner: Fix build error * Planner: Dynamic generation of semester from date * PlannerTest: Add JUnit test for generateSemester * Update documentation for view command * Add view command for monthly calendar view * Fix Codacy issue * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * UserGuide: Update user guide documentation * Moved Semester generation code * Planner: remove unused imports * Semester: undo minor change * DeveloperGuide: Update documentation on initialization of Semester * Update Developer Guide for FindCommand (#118) * Update UserGuide.adoc with "Managing Slots" and diagrams (#119) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update UserGuide.adoc with Managing Slots and diagrams * Solved unchecked or unsafe operation warnings * Edit Data Classes, remove unnecessary dependencies (#120) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Add tests for Add, Edit and Delete commands and optimise code * Fix checkstyle error * Update UserGuide.adoc with Managing Slots and diagrams * Solved unchecked or unsafe operation warnings * Edit Data Classes, remove unnecessary dependencies * Update entire project to follow better software engineering practices (#123) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update UserGuide.adoc with Managing Slots and diagrams * Solved unchecked or unsafe operation warnings * Update entire project to follow better software engineering practices * Edit UiClassDiagram.uml and png * Update view command (#124) > > > ![Codacy](https://camo.githubusercontent.com/b72992711a855bd9a03bfbdfc5ef7fcf528482f5/68747470733a2f2f6170702e636f646163792e636f6d2f6173736574732f696d616765732f66617669636f6e2e706e67) Here is an overview of what got changed by this pull request: > > ```diff > Complexity increasing per file > ============================== > - src/planmysem/logic/parser/ViewCommandParser.java 4 > > ``` > > See the complete overview on [Codacy](https://app.codacy.com/app/CS2113T-T08-3/main/pullRequest?prid=3354301&bid=12090529) To be expected. * Enhance FindCommand to use Levenshtein Distance (#31) * Enhance FindCommand to use Levenshtein Distance * Fix Checkstyle * Fix codacy issues * resolve merge conflict * Merge (#33) * Enhance FindCommand to use Levenshtein Distance (#126) * Update diagrams and minor text in DeveloperGuide and AboutUs (#127) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update UserGuide.adoc with Managing Slots and diagrams * Solved unchecked or unsafe operation warnings * Update entire project to follow better software engineering practices * Edit UiClassDiagram.uml and png * Update UiClassDiagram.uml * Update diagrams and minor text in DeveloperGuide and AboutUs * Update DeveloperGuide, manipulating slots * Update DeveloperGuide fix typo * Update "lastshownslots" mechanism * Update Messages.java refactor some functions * Merge (#36) * Enhance FindCommand to use Levenshtein Distance * Fix Checkstyle * Enhance FindCommand to use Levenshtein Distance (#126) * Update diagrams and minor text in DeveloperGuide and AboutUs (#127) * v1.1 * fix some errors and typos * Refactor entire project, remove all traces of Addressbook * Update developer guide for ExportCommandP (#80) * Update documentation for view command (#81) * Remove remaining Addressbook classes * Refactor some classes * fix missing files issue * Add test cases for add function, Utils and other code enhancements * fix codacy issues * fix codacy issues * Add tests for Utils * Add diagrams * Update Ui.png * fix issue with Ui.png * Update Codacy Badge link due to reinitialization. * Enhance ordering of slots printed * Update UserGuide.adoc with feedback from peers * Update UserGuide.adoc with nicer tables * Update UserGuide.adoc: fix formatting issues * UserGuide.adoc Remove potential Netlify breaking code * README.adoc revert changes * UserGuide.adoc revert Netlify breakdown test code * Update UserGuide.adoc with Managing Slots and diagrams * Solved unchecked or unsafe operation warnings * Update entire project to follow better software engineering practices * Edit UiClassDiagram.uml and png * Update UiClassDiagram.uml * Update diagrams and minor text in DeveloperGuide and AboutUs * Update DeveloperGuide, manipulating slots * Update DeveloperGuide fix typo * Update "lastshownslots" mechanism * Update Messages.java refactor some functions * resolve merge conflict * Edit FindCommand to generate lastShownList * Resolve checkstyle * Resolve merge conflicts * Edit FindCommand to generate lastShownList (#128) (#35) * Add UndoRedo Command * ERROR:parsing file format * Fix storage bug * Fix checkstyle errors unused imports * Update DeveloperGuide.adoc with Slot management details * Update DeveloperGuide.adoc added whitespace between sections * Update help messages and test cases * Refined test cases * Update Ui.png * Add tests for Model classes * Update LogicManager.java with more tests * Revert test cases that fail under Appveyor * Update DeveloperGuide.adoc typos --- docs/DeveloperGuide.adoc | 46 +- docs/UserGuide.adoc | 8 +- docs/diagrams/LogicClassDiagram.uml | 144 +-- docs/images/Ui.png | Bin 25098 -> 13521 bytes src/planmysem/Main.java | 2 +- src/planmysem/common/Messages.java | 8 +- src/planmysem/common/Utils.java | 9 +- .../exceptions/IllegalValueException.java | 8 - src/planmysem/logic/LogicManager.java | 30 +- .../logic/commands/CommandResult.java | 5 - .../logic/commands/DeleteCommand.java | 12 +- src/planmysem/logic/commands/EditCommand.java | 5 +- src/planmysem/logic/commands/ExitCommand.java | 9 +- .../logic/commands/ExportCommand.java | 9 +- src/planmysem/logic/commands/FindCommand.java | 8 +- src/planmysem/logic/commands/HelpCommand.java | 10 +- .../logic/commands/HistoryCommand.java | 4 + .../logic/commands/ImportCommand.java | 5 +- src/planmysem/logic/commands/ListCommand.java | 3 +- src/planmysem/logic/commands/RedoCommand.java | 4 + src/planmysem/logic/commands/UndoCommand.java | 4 + .../logic/parser/EditCommandParser.java | 20 +- src/planmysem/logic/parser/ParserManager.java | 3 + .../parser/exceptions/ParseException.java | 4 - src/planmysem/model/Model.java | 5 + src/planmysem/model/ModelManager.java | 14 +- src/planmysem/model/Planner.java | 13 +- src/planmysem/model/VersionedPlanner.java | 6 + .../model/recurrence/Recurrence.java | 19 +- src/planmysem/model/semester/Day.java | 10 +- src/planmysem/model/semester/Semester.java | 15 +- src/planmysem/model/slot/Slot.java | 22 +- src/planmysem/ui/Formatter.java | 42 - src/planmysem/ui/Gui.java | 7 +- src/planmysem/ui/MainWindow.java | 2 +- test/data/StorageFileTest/InvalidData.txt | 6 - test/data/StorageFileTest/ValidData.txt | 956 ------------------ test/java/planmysem/common/UtilsTest.java | 30 +- .../logic/Commands/AddCommandTest.java | 55 +- .../logic/Commands/ClearCommandTest.java | 1 + .../logic/Commands/CommandResultTest.java | 26 + .../logic/Commands/CommandTestUtil.java | 107 +- .../logic/Commands/DeleteCommandTest.java | 42 +- .../logic/Commands/EditCommandTest.java | 92 +- .../logic/Commands/ExitCommandTest.java | 4 +- .../logic/Commands/ExportCommandTest.java | 2 +- .../logic/Commands/FindCommandTest.java | 35 +- .../{parser => Commands}/HelpCommandTest.java | 3 +- .../logic/Commands/ListCommandTest.java | 29 +- .../planmysem/logic/LogicManagerTest.java | 113 ++- .../logic/parser/AddCommandParserTest.java | 62 +- .../logic/parser/CommandParserTestUtil.java | 6 +- .../logic/parser/DeleteCommandParserTest.java | 4 +- .../logic/parser/EditCommandParserTest.java | 43 +- .../logic/parser/ParserManagerTest.java | 134 ++- .../planmysem/model/ModelManagerTest.java | 106 ++ test/java/planmysem/model/PlannerTest.java | 152 +-- .../model/Recurrence/RecurrenceTest.java | 95 ++ .../planmysem/model/Semester/DayTest.java | 99 ++ .../model/Semester/SemesterTest.java | 255 +++++ test/java/planmysem/model/Slot/SlotTest.java | 134 +++ .../planmysem/model/VersionedPlannerTest.java | 95 ++ .../planmysem/storage/StorageFileTest.java | 110 +- test/java/planmysem/testutil/SlotBuilder.java | 90 +- test/java/planmysem/util/TestUtil.java | 3 + test/model/StorageFileTest/InvalidData.txt | 1 + test/model/StorageFileTest/ValidData.txt | 1 + 67 files changed, 1528 insertions(+), 1878 deletions(-) delete mode 100644 test/data/StorageFileTest/InvalidData.txt delete mode 100644 test/data/StorageFileTest/ValidData.txt create mode 100644 test/java/planmysem/logic/Commands/CommandResultTest.java rename test/java/planmysem/logic/{parser => Commands}/HelpCommandTest.java (95%) create mode 100644 test/java/planmysem/model/ModelManagerTest.java create mode 100644 test/java/planmysem/model/Recurrence/RecurrenceTest.java create mode 100644 test/java/planmysem/model/Semester/DayTest.java create mode 100644 test/java/planmysem/model/Semester/SemesterTest.java create mode 100644 test/java/planmysem/model/Slot/SlotTest.java create mode 100644 test/java/planmysem/model/VersionedPlannerTest.java create mode 100644 test/model/StorageFileTest/InvalidData.txt create mode 100644 test/model/StorageFileTest/ValidData.txt diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index b592a3ae8..4dab1d0d0 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -19,6 +19,7 @@ endif::[] By: `T08-3` Since: `Jan 2019` Licence: `MIT` + == Introduction Welcome to *PlanMySem*! @@ -95,10 +96,9 @@ Do not disable them. If you have disabled them, go to `File` > `Settings` > `Plu . Open the `StorageFile` file and check for any code errors . Open a console and run the command `gradlew processResources` (Mac/Linux: `./gradlew processResources`). It should finish with the `BUILD SUCCESSFUL` message. + This will generate all resources required by the application and tests. -. Open link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow.java`] and check for any code errors +. Open link:{repoURL}/src/planmysem/ui/MainWindow.java[`MainWindow.java`] and check for any code errors .. Due to an ongoing https://youtrack.jetbrains.com/issue/IDEA-189060[issue] with some of the newer versions of IntelliJ, code errors may be detected even if the project can be built and run successfully .. To resolve this, place your cursor over any of the code section highlighted in red. Press kbd:[ALT + ENTER], and select `Add '--add-modules=...' to module compiler options` for each error -. Repeat this for the test folder as well (e.g. check link:{repoURL}/src/test/java/seedu/address/ui/HelpWindowTest.java[`HelpWindowTest.java`] for code errors, and if so, resolve it the same way) {zwsp} {zwsp} @@ -176,6 +176,7 @@ When you are ready to start coding, .Architecture Diagram image::Architecture.png[width="800"] +{zwsp} The *_Architecture Diagram_* given above explains the high-level design of the App. Given below is a quick overview of each component. @@ -216,6 +217,7 @@ The _Sequence Diagram_ below shows how the components interact with each other f .Component interactions for `delete 1` command image::SDforDeleteSlot.png[width="800"] +{zwsp} The sections below give more details of each component. {zwsp} @@ -226,7 +228,8 @@ The sections below give more details of each component. === UI component .Structure of the UI Component -image::UiClassDiagram.png[width="800"] +image::UiClassDiagram.png[width="400"] +{zwsp} *API* : link:{repoURL}/src/planmysem/ui/Ui.java[`Ui.java`] @@ -234,7 +237,7 @@ The UI consists of a `MainWindow` that is made up of just `commandInput` and `ou This application is mainly a text-based application, hence here are not much componenets here. The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. -For example, the layout of the link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] +For example, the layout of the link:{repoURL}/src/planmysem/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] The `UI` component, @@ -250,6 +253,7 @@ The `UI` component, [[fig-LogicClassDiagram]] .Structure of the Logic Component image::LogicClassDiagram.png[width="800"] +{zwsp} *API* : link:{repoURL}/src/planmysem/logic/Logic.java[`Logic.java`] @@ -272,7 +276,8 @@ image::SDforDeleteSlot.png[width="800"] === Model component .Overall structure of the Model Component -image::ModelClassDiagram.png[width="600"] +image::ModelClassDiagram.png[width="400"] +{zwsp} *API* : link:{repoURL}/src/planmysem/model/Model.java[`Model.java`] {zwsp} @@ -329,13 +334,14 @@ Notice how `Slot` does not hold it's end time but rather it holds the `duration` .Structure of the Storage Component image::StorageClassDiagram.png[width="400"] +{zwsp} *API* : link:{repoURL}/src/planmysem/storage/Storage.java[`Storage.java`] The `Storage` component, * can save `UserPref` objects in json format and read it back. -* can save the Address Book data in json format and read it back. +* can save the Planner data in json format and read it back. {zwsp} {zwsp} @@ -800,14 +806,17 @@ Given below is an example usage scenario and how the undo/redo mechanism behaves Step 1. The user launches the application for the first time. The `VersionedPlanner` will be initialized with the initial planner state, and the `currentStatePointer` pointing to that single planner state. image::UndoRedoStartingStateListDiagram.png[width="800"] +{zwsp} Step 2. The user executes `delete 5` command to delete the 5th `Slot` in the planner. The `delete` command calls `Model#commitPlanner()`, causing the modified state of the planner after the `delete 5` command executes to be saved in the `plannerStateList`, and the `currentStatePointer` is shifted to the newly inserted planner state. image::UndoRedoNewCommand1StateListDiagram.png[width="800"] +{zwsp} Step 3. The user executes `add n/CS2113T ...` to add a new slot. The `add` command also calls `Model#commitPlanner()`, causing another modified planner state to be saved into the `plannerStateList`. image::UndoRedoNewCommand2StateListDiagram.png[width="800"] +{zwsp} [NOTE] If a command fails its execution, it will not call `Model#commitPlanner()`, so the planner state will not be saved into the `plannerStateList`. @@ -815,6 +824,7 @@ If a command fails its execution, it will not call `Model#commitPlanner()`, so t Step 4. The user now decides that adding the `Slot` was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undo()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous planner state, and restores the planner to that state. image::UndoRedoExecuteUndoStateListDiagram.png[width="800"] +{zwsp} [NOTE] If the `currentStatePointer` is at index 0, pointing to the initial planner state, then there are no previous planner states to restore. The `undo` command uses `Model#canUndo()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo. @@ -831,10 +841,12 @@ If the `currentStatePointer` is at index `plannerStateList.size() - 1`, pointing Step 5. The user then decides to execute the command `list`. Commands that do not modify the planner, such as `list`, will usually not call `Model#commitPlanner()`, `Model#undoPlanner()` or `Model#redoPlanner()`. Thus, the `plannerStateList` remains unchanged. image::UndoRedoNewCommand3StateListDiagram.png[width="800"] +{zwsp} Step 6. The user executes `clear`, which calls `Model#commitPlanner()`. Since the `currentStatePointer` is not pointing at the end of the `plannerStateList`, all planner states after the `currentStatePointer` will be purged. We designed it this way because it no longer makes sense to redo the `add n/David ...` command. This is the behavior that most modern desktop applications follow. image::UndoRedoNewCommand4StateListDiagram.png[width="800"] +{zwsp} The following activity diagram summarizes what happens when a user executes a new command: @@ -929,7 +941,7 @@ image::UndoRedoActivityDiagram.png[width="650"] === Data Encryption / Decryption feature -The storageFile file "PlanMySem.txt" is encrypted to prevent easy access of the user's calendar. +The storage file "PlanMySem.txt" is encrypted to prevent easy access of the user's calendar. We are encrypting and decrypting the data using the Java Cypher class. This feature is implemented through creating a Encryptor that contains encrypt and decrypt methods. The encrypt method takes a String object as an argument and returns a encrypted String object. The decrypt method takes in a String object as an argument and returns the decrypted message as a String object. @@ -958,7 +970,7 @@ In our implementation, we have chosen not to export the tags into the .ics file. * **Alternative 1 (current choice):** Ignore tags when exporting. ** Pros: Easier to implement as iCalendar does not have in-built tag fields. ** Cons: Not all the information about the slots will be retained. -** Reason for choice: We do not have much control over other applications, and importing and exporting .ics within *PlanMySem* can be done using the storageFile .txt file. +** Reason for choice: We do not have much control over other applications, and importing and exporting .ics within *PlanMySem* can be done using the storage .txt file. * **Alternative 2:** Use the notes field and a tag identifier to save the tags. ** Pros: All the information from the semester will be exported. ** Cons: Requires other applications to be coded to read these tag identifiers and also to store and use the tags in their functions. @@ -1140,7 +1152,7 @@ To run tests in headless mode, open a console and run the command `gradlew clean . _Unit tests_ targeting the lowest level methods/classes. + e.g. `PlanMySem.commons.UtilTest` . _Integration tests_ that are checking the integration of multiple code units (those code units are assumed to be working). + -e.g. `PlanMySem.storageFile.StorageManagerTest` +e.g. `PlanMySem.storage.StorageManagerTest` . Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together. + e.g. `PlanMySem.logicManager.LogicTest`, `PlanMySem.parse,ParserTest` {zwsp} @@ -1199,7 +1211,10 @@ Here are the steps to create a new release. === Managing Dependencies -A project often depends on third-party libraries. For example, Address Book depends on the https://github.com/FasterXML/jackson[Jackson library] for JSON parsing. Managing these _dependencies_ can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives: +Projects often depends on third-party libraries. +For example, *PlanMySem* depends on the https://github.com/FasterXML/jackson[Jackson library] for JSON parsing. +Managing these _dependencies_ can be automated using Gradle. +For example, Gradle can download the dependencies automatically, which is better than these alternatives: [loweralpha] . Include those libraries in the repo (this bloats the repo size) @@ -1290,7 +1305,7 @@ A project often depends on third-party libraries. For example, Address Book depe //* Solution //** You can modify the existing test methods for `PersonCard` 's to include testing the tag's color as well. //** See this https://github.com/se-edu/addressbook-level4/pull/798[PR] for the full solution. -//*** The PR uses the hash code of the tag names to generate a color. This is deliberately designed to ensure consistent colors each time the application runs. You may wish to expand on this design to include additional features, such as allowing users to set their own tag colors, and directly saving the colors to storageFile, so that tags retain their colors even if the hash code algorithm changes. +//*** The PR uses the hash code of the tag names to generate a color. This is deliberately designed to ensure consistent colors each time the application runs. You may wish to expand on this design to include additional features, such as allowing users to set their own tag colors, and directly saving the colors to storage, so that tags retain their colors even if the hash code algorithm changes. //**** // //. Modify link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] such that link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay`] can show a different style on error (currently it shows the same regardless of errors). @@ -1342,7 +1357,7 @@ A project often depends on third-party libraries. For example, Address Book depe //[discrete] //==== `Storage` component // -//*Scenario:* You are in charge of `storageFile`. For your next project milestone, your team plans to implement a new feature of saving the address book to the cloud. However, the current implementation of the application constantly saves the address book after the execution of each command, which is not ideal if the user is working on limited internet connection. Your team decided that the application should instead save the changes to a temporary local backup file first, and only upload to the cloud after the user closes the application. Your job is to implement a backup API for the address book storageFile. +//*Scenario:* You are in charge of `storage`. For your next project milestone, your team plans to implement a new feature of saving the address book to the cloud. However, the current implementation of the application constantly saves the address book after the execution of each command, which is not ideal if the user is working on limited internet connection. Your team decided that the application should instead save the changes to a temporary local backup file first, and only upload to the cloud after the user closes the application. Your job is to implement a backup API for the address book storage. // //[TIP] //Do take a look at <> before attempting to modify the `Storage` component. @@ -1351,8 +1366,8 @@ A project often depends on third-party libraries. For example, Address Book depe //+ //**** //* Hint -//** Add the API method in link:{repoURL}/src/main/java/seedu/address/storageFile/AddressBookStorage.java[`AddressBookStorage`] interface. -//** Implement the logicManager in link:{repoURL}/src/main/java/seedu/address/storageFile/StorageManager.java[`StorageManager`] and link:{repoURL}/src/main/java/seedu/address/storageFile/JsonAddressBookStorage.java[`JsonAddressBookStorage`] class. +//** Add the API method in link:{repoURL}/src/main/java/seedu/address/storage/AddressBookStorage.java[`AddressBookStorage`] interface. +//** Implement the logicManager in link:{repoURL}/src/main/java/seedu/address/storage/StorageManager.java[`StorageManager`] and link:{repoURL}/src/main/java/seedu/address/storage/JsonAddressBookStorage.java[`JsonAddressBookStorage`] class. //* Solution //** See this https://github.com/se-edu/addressbook-level4/pull/594[PR] for the full solution. //**** @@ -1440,7 +1455,7 @@ A project often depends on third-party libraries. For example, Address Book depe //. Modify link:{repoURL}/src/main/java/seedu/address/model/util/SampleDataUtil.java/[`SampleDataUtil`] to add remarks for the sample model (delete your `model/addressbook.json` so that the application will load the sample model when you launch it.) // //===== [Step 6] Storage: Add `Remark` field to `JsonAdaptedPerson` class -//We now have `Remark` s for `Person` s, but they will be gone when we exit the application. Let's modify link:{repoURL}/src/main/java/seedu/address/storageFile/JsonAdaptedPerson.java[`JsonAdaptedPerson`] to include a `Remark` field so that it will be saved. +//We now have `Remark` s for `Person` s, but they will be gone when we exit the application. Let's modify link:{repoURL}/src/main/java/seedu/address/storage/JsonAdaptedPerson.java[`JsonAdaptedPerson`] to include a `Remark` field so that it will be saved. // //**Main:** // @@ -1749,7 +1764,6 @@ These instructions only provide a starting point for testers to work on; testers {zwsp} - === Saving data . Dealing with missing/corrupted data files diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index ecd59464b..c4057feb4 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -383,7 +383,7 @@ image::Ui.png[width="790"] {zwsp} [[history]] -=== Listing previous input commands : `history` `[coming in v2.0]` +=== Listing previous input commands : `history` Lists all the commands that you have entered in reverse chronological order. + Format: `history` {zwsp} @@ -391,7 +391,7 @@ Format: `history` {zwsp} [[undo]] -=== Undoing previous command : `undo` `[coming in v2.0]` +=== Undoing previous command : `undo` Restores the planner to the state before the previous command was executed. + Format: `undo` @@ -402,7 +402,7 @@ The `clear` command cannot be undone. {zwsp} [[redo]] -=== Redoing the previously undone command : `redo` `[coming in v2.0]` +=== Redoing the previously undone command : `redo` Reverses the most recent `undo` command. + Format: `redo` {zwsp} @@ -417,7 +417,7 @@ Planner data is automatically encrypted before saving and decrypted before loadi {zwsp} [[import]] -=== Importing .ics formatted files `[coming in v2.0]` +=== Importing .ics formatted files You can import an .ics file into the planner. Format: `import filename` [NOTE] diff --git a/docs/diagrams/LogicClassDiagram.uml b/docs/diagrams/LogicClassDiagram.uml index 9854bca26..8ff2ad8a5 100644 --- a/docs/diagrams/LogicClassDiagram.uml +++ b/docs/diagrams/LogicClassDiagram.uml @@ -3,137 +3,43 @@ JAVA planmysem.storage.Storage - planmysem.logic.commands.Command - planmysem.logic.parser.ParserManager - planmysem.logic.commands.EditCommand - planmysem.logic.commands.AddCommand - planmysem.logic.CommandHistory - planmysem.logic.commands.CommandResult - planmysem.logic.Logic - planmysem.logic.parser.Parser - planmysem.logic.LogicManager + planmysem.logic.commands.Command + planmysem.logic.parser.ParserManager + planmysem.logic.commands.EditCommand + planmysem.logic.commands.AddCommand + planmysem.logic.Logic + planmysem.logic.commands.CommandResult + planmysem.logic.CommandHistory + planmysem.logic.parser.Parser + planmysem.logic.LogicManager - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - + + - - + + + planmysem.logic.commands.CommandResult + All private diff --git a/docs/images/Ui.png b/docs/images/Ui.png index c5a439677c02b11fd728249da048c1a16ce54154..df7714795016436a797f3ea365761ae0db46eff5 100644 GIT binary patch literal 13521 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 Hh5!Em)k|Ei diff --git a/src/planmysem/Main.java b/src/planmysem/Main.java index 2ee142f73..b00f00f98 100644 --- a/src/planmysem/Main.java +++ b/src/planmysem/Main.java @@ -17,7 +17,7 @@ public class Main extends Application implements Stoppable { /** * Version info of the program. */ - public static final String VERSION = "PlanMySem - Version 1.2"; + public static final String VERSION = "PlanMySem - Version 1.3"; public static void main(String[] args) { launch(args); diff --git a/src/planmysem/common/Messages.java b/src/planmysem/common/Messages.java index 76d7dd4d9..6e05152bb 100644 --- a/src/planmysem/common/Messages.java +++ b/src/planmysem/common/Messages.java @@ -19,26 +19,20 @@ public class Messages { public static final String MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL = "Invalid command format! \n%1$s\n\n%2$s"; public static final String MESSAGE_INVALID_MULTIPLE_PARAMS = "Either search by NAME or by TAG only, not both."; public static final String MESSAGE_INVALID_SLOT_DISPLAYED_INDEX = "The slot index provided is invalid"; - public static final String MESSAGE_SLOT_NOT_IN_PLANNER = "Slot could not be found in Planner"; - public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; - public static final String MESSAGE_SLOTS_LISTED_OVERVIEW = "%1$d slots listed!"; public static final String MESSAGE_PROGRAM_LAUNCH_ARGS_USAGE = "Launch command format: " + "java Main [STORAGE_FILE_PATH]"; public static final String MESSAGE_WELCOME = "Welcome to PlanMySem!"; public static final String MESSAGE_USING_STORAGE_FILE = "Using storage file : %1$s"; - + public static final String MESSAGE_NOTHING_TO_EDIT = "There are no details to edit."; public static final String MESSAGE_INVALID_DATE = "Date have to be in either these two formats:" + "\n\tIn the form of \"dd-mm\". e.g. \"01-01\"" + "\n\tIn the form of \"dd-mm-yyyy\". e.g. \"01-01-2019\"" + "\n\tOr perhaps target the next day of week. e.g. \"Monday\", \"mon\", \"1\""; - public static final String MESSAGE_INVALID_TIME = "Time have to be in either these two formats:" + "\n\t24-Hour in the form of “hh:mm”. e.g. \"23:00\"" + "\n\t12-Hour in the form of `hh:mm+AM|PM`. e.g. \"12:30am\"" + "\n\tOr perhaps type a duration in minutes. e.g. \"60\" to represent 60 minutes"; - public static final String MESSAGE_INVALID_TAG = "Tags cannot be empty !"; - public static final String MESSAGE_ILLEGAL_VALUE = "Illegal value detected!"; public static final String MESSAGE_ILLEGAL_WEEK_VALUE = "No such week is found in the current semester!"; public static final String MESSAGE_DATE_OUT_OF_BOUNDS = "No such date is found in the current semester!"; diff --git a/src/planmysem/common/Utils.java b/src/planmysem/common/Utils.java index cf124f6fa..b7eabc738 100644 --- a/src/planmysem/common/Utils.java +++ b/src/planmysem/common/Utils.java @@ -63,7 +63,7 @@ public static int parseDay(String unknown) { return -1; } String day = unknown.trim().toLowerCase(); - int result = -1; + int result; switch (day) { case "monday": case "mon": @@ -131,13 +131,6 @@ public static LocalDate parseDate(String date) { return null; } - /** - * Parse LocalDate to String. - */ - public static String parseDate(LocalDate date) { - return date.format(DateTimeFormatter.ofPattern("d-MM-yyyy")); - } - /** * Parse String to 12 hour or 24 hour time format. */ diff --git a/src/planmysem/common/exceptions/IllegalValueException.java b/src/planmysem/common/exceptions/IllegalValueException.java index bef2195df..7f36f81c8 100644 --- a/src/planmysem/common/exceptions/IllegalValueException.java +++ b/src/planmysem/common/exceptions/IllegalValueException.java @@ -10,12 +10,4 @@ public class IllegalValueException extends Exception { public IllegalValueException(String message) { super(message); } - - /** - * @param message should contain relevant information on the failed constraint(s) - * @param cause of the main exception - */ - public IllegalValueException(String message, Throwable cause) { - super(message, cause); - } } diff --git a/src/planmysem/logic/LogicManager.java b/src/planmysem/logic/LogicManager.java index abf6b39a5..8814498cd 100644 --- a/src/planmysem/logic/LogicManager.java +++ b/src/planmysem/logic/LogicManager.java @@ -23,28 +23,18 @@ public class LogicManager implements Logic { public static final String STORAGE_ERROR = "Could not save data to file: "; - private final Storage storageFile; + private final Storage storage; private final Model model; private final CommandHistory history; private final ParserManager parserManager; - public LogicManager(Storage storageFile) throws Exception { - this.storageFile = storageFile; - this.model = new ModelManager(storageFile.load()); + public LogicManager(Storage storage) throws Exception { + this.storage = storage; + this.model = new ModelManager(storage.load()); this.history = new CommandHistory(); this.parserManager = new ParserManager(); } - @Override - public String getStorageFilePath() { - return storageFile.getPath(); - } - - @Override - public List>> getLastShownSlots() { - return model.getLastShownList(); - } - @Override public CommandResult execute(String userCommandText) throws CommandException, ParseException { CommandResult result; @@ -55,7 +45,7 @@ public CommandResult execute(String userCommandText) throws CommandException, Pa history.add(userCommandText); } try { - storageFile.save(model.getPlanner()); + storage.save(model.getPlanner()); } catch (StorageFile.StorageOperationException soe) { throw new CommandException(STORAGE_ERROR + soe, soe); } @@ -63,6 +53,16 @@ public CommandResult execute(String userCommandText) throws CommandException, Pa return result; } + @Override + public String getStorageFilePath() { + return storage.getPath(); + } + + @Override + public List>> getLastShownSlots() { + return model.getLastShownList(); + } + @Override public ObservableList getHistory() { return history.getHistory(); diff --git a/src/planmysem/logic/commands/CommandResult.java b/src/planmysem/logic/commands/CommandResult.java index 07325bba9..3f3e81ded 100644 --- a/src/planmysem/logic/commands/CommandResult.java +++ b/src/planmysem/logic/commands/CommandResult.java @@ -29,11 +29,6 @@ public CommandResult(String feedbackToUser) { slots = null; } - public CommandResult(String feedbackToUser, Map> slots) { - this.feedbackToUser = feedbackToUser; - this.slots = slots; - } - /** * Returns list of Slots relevant to the command command result, if any. */ diff --git a/src/planmysem/logic/commands/DeleteCommand.java b/src/planmysem/logic/commands/DeleteCommand.java index 17240583b..b5a402500 100644 --- a/src/planmysem/logic/commands/DeleteCommand.java +++ b/src/planmysem/logic/commands/DeleteCommand.java @@ -1,5 +1,7 @@ package planmysem.logic.commands; +import static planmysem.common.Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX; + import java.time.LocalDate; import java.util.HashSet; import java.util.Map; @@ -33,6 +35,8 @@ public class DeleteCommand extends Command { public static final String MESSAGE_SUCCESS_NO_CHANGE = "No Slots were deleted.\n\n%1$s"; public static final String MESSAGE_SUCCESS = "%1$s Slots deleted.\n\n%2$s\n%3$s"; + public static final String MESSAGE_SLOT_NOT_IN_PLANNER = + "Slot could not be found in Planner. Perhaps it was previously deleted."; private final Set tags = new HashSet<>(); private final int targetIndex; @@ -75,6 +79,12 @@ public CommandResult execute(Model model, CommandHistory commandHistory) throws } else { try { final Pair> target = model.getLastShownItem(targetIndex); + + // check if slot still exist + if (!model.slotExists(target.getKey(), target.getValue().getValue())) { + throw new CommandException(MESSAGE_SLOT_NOT_IN_PLANNER); + } + selectedSlots.put(target.getKey(), target.getValue()); model.removeSlot(target); @@ -82,7 +92,7 @@ public CommandResult execute(Model model, CommandHistory commandHistory) throws messageSelected = Messages.craftSelectedMessage(targetIndex); messageSlots = Messages.craftSelectedMessage("Deleted Slot:", selectedSlots); } catch (IndexOutOfBoundsException ie) { - throw new CommandException(Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); + throw new CommandException(MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); } } model.commit(); diff --git a/src/planmysem/logic/commands/EditCommand.java b/src/planmysem/logic/commands/EditCommand.java index 134fa209b..7441da858 100644 --- a/src/planmysem/logic/commands/EditCommand.java +++ b/src/planmysem/logic/commands/EditCommand.java @@ -28,15 +28,15 @@ public class EditCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edit single or multiple slots in the Planner." + "\n\tParameters: " + "\n\t\tMandatory: t/TAG... or INDEX" - + "\n\t\tOptional Parameters: [nst/NEW_START_TIME] [net/NEW_END_TIME|DURATION] " + + "\n\t\tOptional: [nst/NEW_START_TIME] [net/NEW_END_TIME|DURATION] " + "[nl/NEW_LOCATION] [nd/NEW_DESCRIPTION]" + "\n\tExample 1: " + COMMAND_WORD + " t/CS2113T t/Tutorial nl/COM2 04-01" + "\n\tExample 2: " + COMMAND_WORD + " 2 nl/COM2 04-01"; - public static final String MESSAGE_SUCCESS_NO_CHANGE = "No Slots were edited.\n\n%1$s"; public static final String MESSAGE_SUCCESS = "%1$s Slots edited.\n\n%2$s\n%3$s"; + public static final String MESSAGE_SUCCESS_NO_CHANGE = "No Slots were edited.\n\n%1$s"; private final LocalDate date; private final LocalTime startTime; @@ -126,6 +126,7 @@ public CommandResult execute(Model model, CommandHistory commandHistory) throws throw new CommandException(Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); } } + model.commit(); return new CommandResult(String.format(MESSAGE_SUCCESS, selectedSlots.size(), messageSelected, messageSlots)); diff --git a/src/planmysem/logic/commands/ExitCommand.java b/src/planmysem/logic/commands/ExitCommand.java index 7433fbbb2..7f27f471c 100644 --- a/src/planmysem/logic/commands/ExitCommand.java +++ b/src/planmysem/logic/commands/ExitCommand.java @@ -9,14 +9,13 @@ public class ExitCommand extends Command { public static final String COMMAND_WORD = "exit"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Exits the program.\n\t" - + "Example: " + COMMAND_WORD; - public static final String MESSAGE_EXIT_ACKNOWEDGEMENT = "Exiting PlanMySem as requested ..."; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Exits the program." + + "\n\tExample: " + COMMAND_WORD; + public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting PlanMySem as requested ..."; @Override public CommandResult execute(Model model, CommandHistory commandHistory) { - return new CommandResult(MESSAGE_EXIT_ACKNOWEDGEMENT); + return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT); } } diff --git a/src/planmysem/logic/commands/ExportCommand.java b/src/planmysem/logic/commands/ExportCommand.java index 2051b0c77..4b7d35419 100644 --- a/src/planmysem/logic/commands/ExportCommand.java +++ b/src/planmysem/logic/commands/ExportCommand.java @@ -14,9 +14,10 @@ public class ExportCommand extends Command { public static final String COMMAND_WORD = "export"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Delete single or multiple slots in the Planner." - + "\n\tExample: " + COMMAND_WORD; - public static final String MESSAGE_EXPORT_ACKNOWEDGEMENT = "Calendar exported"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Export the planner as a .ics file." + + "\n\tParameters: filename" + + "\n\tExample: " + COMMAND_WORD + " my_planner.ics"; + public static final String MESSAGE_EXPORT_ACKNOWLEDGEMENT = "Calendar exported"; @Override public CommandResult execute(Model model, CommandHistory commandHistory) { @@ -29,7 +30,7 @@ public CommandResult execute(Model model, CommandHistory commandHistory) { e.printStackTrace(); } - return new CommandResult(MESSAGE_EXPORT_ACKNOWEDGEMENT); + return new CommandResult(MESSAGE_EXPORT_ACKNOWLEDGEMENT); } } diff --git a/src/planmysem/logic/commands/FindCommand.java b/src/planmysem/logic/commands/FindCommand.java index 48043fd61..d3357a20f 100644 --- a/src/planmysem/logic/commands/FindCommand.java +++ b/src/planmysem/logic/commands/FindCommand.java @@ -31,10 +31,10 @@ public class FindCommand extends Command { public static final String COMMAND_WORD_SHORT = "f"; private static final String MESSAGE_SUCCESS = "%1$s Slots listed.\n%2$s"; private static final String MESSAGE_SUCCESS_NONE = "0 Slots listed.\n"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Finds all slots whose name " - + "contains the specified keywords (case-sensitive).\n\t" - + "Parameters: KEYWORD [MORE_KEYWORDS]...\n\t" - + "Example: " + COMMAND_WORD + "n/CS"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all slots whose name " + + "contains the specified keywords (not case-sensitive)." + + "\n\tMandatory Parameters: n/NAME or t/TAG..." + + "\n\tExample: " + COMMAND_WORD + " n/CS1010"; private final String keyword; private final boolean isFindByName; diff --git a/src/planmysem/logic/commands/HelpCommand.java b/src/planmysem/logic/commands/HelpCommand.java index 87212fe01..f173cc831 100644 --- a/src/planmysem/logic/commands/HelpCommand.java +++ b/src/planmysem/logic/commands/HelpCommand.java @@ -10,8 +10,8 @@ public class HelpCommand extends Command { public static final String COMMAND_WORD = "help"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Shows program usage instructions.\n\t" - + "Example: " + COMMAND_WORD; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows program usage instructions." + + "\n\tExample: " + COMMAND_WORD; public static final String MESSAGE_ALL_USAGES = AddCommand.MESSAGE_USAGE + "\n\n" + EditCommand.MESSAGE_USAGE @@ -19,7 +19,11 @@ public class HelpCommand extends Command { + "\n\n" + ListCommand.MESSAGE_USAGE + "\n\n" + FindCommand.MESSAGE_USAGE + "\n\n" + ViewCommand.MESSAGE_USAGE - // + "\n\n" + ViewAllCommand.MESSAGE_USAGE + + "\n\n" + HistoryCommand.MESSAGE_USAGE + + "\n\n" + UndoCommand.MESSAGE_USAGE + + "\n\n" + RedoCommand.MESSAGE_USAGE + + "\n\n" + ExportCommand.MESSAGE_USAGE + + "\n\n" + ImportCommand.MESSAGE_USAGE + "\n\n" + ClearCommand.MESSAGE_USAGE + "\n\n" + HelpCommand.MESSAGE_USAGE + "\n\n" + ExitCommand.MESSAGE_USAGE; diff --git a/src/planmysem/logic/commands/HistoryCommand.java b/src/planmysem/logic/commands/HistoryCommand.java index 720ebf5c7..395ec41e1 100644 --- a/src/planmysem/logic/commands/HistoryCommand.java +++ b/src/planmysem/logic/commands/HistoryCommand.java @@ -15,6 +15,10 @@ public class HistoryCommand extends Command { public static final String COMMAND_WORD = "history"; + public static final String COMMAND_WORD_SHORT = "h"; + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Lists all the commands that you have entered in reverse chronological order." + + "\n\tExample: " + COMMAND_WORD; public static final String MESSAGE_SUCCESS = "Entered commands (from most recent to earliest):\n%1$s"; public static final String MESSAGE_NO_HISTORY = "You have not yet entered any commands."; diff --git a/src/planmysem/logic/commands/ImportCommand.java b/src/planmysem/logic/commands/ImportCommand.java index fdbd8c5a8..c2b249487 100644 --- a/src/planmysem/logic/commands/ImportCommand.java +++ b/src/planmysem/logic/commands/ImportCommand.java @@ -28,9 +28,8 @@ public class ImportCommand extends Command { public static final String COMMAND_WORD = "import"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Imports a .ics file into the Planner." - + "\n\tParameters: " - + "\n\t\tFILENAME"; - + + "\n\tParameters: filename" + + "\n\tExample: " + COMMAND_WORD + " my_outlook_calendar.ics"; public static final String MESSAGE_SUCCESS = "File imported.\n"; public static final String MESSAGE_FILE_NOT_FOUND = "File not found.\n"; public static final String MESSAGE_ERROR_IN_READING_FILE = "Error in reading file.\n"; diff --git a/src/planmysem/logic/commands/ListCommand.java b/src/planmysem/logic/commands/ListCommand.java index 2e1057643..dcb593c67 100644 --- a/src/planmysem/logic/commands/ListCommand.java +++ b/src/planmysem/logic/commands/ListCommand.java @@ -28,8 +28,7 @@ public class ListCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all slots whose name " + "directly matches the specified keyword (not case-sensitive)." - //+ "\n\tOptional Parameters: [past] [next] [all]" - //+ "\n\tDefault: list all" + + "\n\tMandatory Parameters: n/NAME or t/TAG..." + "\n\tExample: " + COMMAND_WORD + " n/CS1010"; private final String keyword; diff --git a/src/planmysem/logic/commands/RedoCommand.java b/src/planmysem/logic/commands/RedoCommand.java index d13279a1e..9811064b5 100644 --- a/src/planmysem/logic/commands/RedoCommand.java +++ b/src/planmysem/logic/commands/RedoCommand.java @@ -13,6 +13,10 @@ public class RedoCommand extends Command { public static final String COMMAND_WORD = "redo"; + public static final String COMMAND_WORD_SHORT = "r"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Reverses the most recent undo command." + + "\n\tExample: " + COMMAND_WORD; + public static final String MESSAGE_SUCCESS = "Redo success!"; public static final String MESSAGE_FAILURE = "No more commands to redo!"; diff --git a/src/planmysem/logic/commands/UndoCommand.java b/src/planmysem/logic/commands/UndoCommand.java index fac095063..34b08bd76 100644 --- a/src/planmysem/logic/commands/UndoCommand.java +++ b/src/planmysem/logic/commands/UndoCommand.java @@ -13,6 +13,10 @@ public class UndoCommand extends Command { public static final String COMMAND_WORD = "undo"; + public static final String COMMAND_WORD_SHORT = "u"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Restores the planner to the state before the previous" + + " undoable command was executed." + + "\n\tExample: " + COMMAND_WORD; public static final String MESSAGE_SUCCESS = "Undo success!"; public static final String MESSAGE_FAILURE = "No more commands to undo!"; diff --git a/src/planmysem/logic/parser/EditCommandParser.java b/src/planmysem/logic/parser/EditCommandParser.java index 4c2993193..0de2c8d5a 100644 --- a/src/planmysem/logic/parser/EditCommandParser.java +++ b/src/planmysem/logic/parser/EditCommandParser.java @@ -1,6 +1,9 @@ package planmysem.logic.parser; import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL; +import static planmysem.common.Messages.MESSAGE_INVALID_TIME; +import static planmysem.common.Messages.MESSAGE_NOTHING_TO_EDIT; import java.time.LocalDate; import java.time.LocalTime; @@ -38,7 +41,8 @@ public EditCommand parse(String args) throws ParseException { if (nst != null) { startTime = Utils.parseTime(nst); if (startTime == null) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, + EditCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME)); } } @@ -50,8 +54,8 @@ public EditCommand parse(String args) throws ParseException { if (duration == -1) { LocalTime endTime = Utils.parseTime(net); if (endTime == null) { - throw new ParseException(String.format( - MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, + EditCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME)); } else { duration = Utils.getDuration(startTime, endTime); } @@ -64,6 +68,16 @@ public EditCommand parse(String args) throws ParseException { String description = getFirstInSet(arguments.get(PREFIX_NEW_DESCRIPTION)); Set newTags = arguments.get(PREFIX_NEW_TAG); + // check if no edits + if ((name == null || name.isEmpty()) + && startTime == null && duration == -1 + && (location == null || location.isEmpty()) + && (description == null || description.isEmpty()) + && newTags == null) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, + EditCommand.MESSAGE_USAGE, MESSAGE_NOTHING_TO_EDIT)); + } + if (index == -1) { return new EditCommand(name, startTime, duration, location, description, tags, newTags); } else { diff --git a/src/planmysem/logic/parser/ParserManager.java b/src/planmysem/logic/parser/ParserManager.java index 335ef63ce..fbbfb2245 100644 --- a/src/planmysem/logic/parser/ParserManager.java +++ b/src/planmysem/logic/parser/ParserManager.java @@ -73,12 +73,15 @@ public Command parseCommand(String userInput) throws ParseException { return new ViewCommandParser().parse(arguments); case HistoryCommand.COMMAND_WORD: + case HistoryCommand.COMMAND_WORD_SHORT: return new HistoryCommand(); case UndoCommand.COMMAND_WORD: + case UndoCommand.COMMAND_WORD_SHORT: return new UndoCommand(); case RedoCommand.COMMAND_WORD: + case RedoCommand.COMMAND_WORD_SHORT: return new RedoCommand(); case ClearCommand.COMMAND_WORD: diff --git a/src/planmysem/logic/parser/exceptions/ParseException.java b/src/planmysem/logic/parser/exceptions/ParseException.java index 057d24dad..46e5bdb8f 100644 --- a/src/planmysem/logic/parser/exceptions/ParseException.java +++ b/src/planmysem/logic/parser/exceptions/ParseException.java @@ -10,8 +10,4 @@ public class ParseException extends IllegalValueException { public ParseException(String message) { super(message); } - - public ParseException(String message, Throwable cause) { - super(message, cause); - } } diff --git a/src/planmysem/model/Model.java b/src/planmysem/model/Model.java index cdc1f2d84..d9a8a68ef 100644 --- a/src/planmysem/model/Model.java +++ b/src/planmysem/model/Model.java @@ -84,6 +84,11 @@ void editSlot(LocalDate targetDate, ReadOnlySlot targetSlot, LocalDate date, */ Day getDay(LocalDate date); + /** + * check if Slot exists in some day. + */ + boolean slotExists(LocalDate date, ReadOnlySlot slot); + /** * gets all slots in the Planner containing all specified tags. */ diff --git a/src/planmysem/model/ModelManager.java b/src/planmysem/model/ModelManager.java index 27c5b7cf0..33c9b28cb 100644 --- a/src/planmysem/model/ModelManager.java +++ b/src/planmysem/model/ModelManager.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import javafx.util.Pair; @@ -47,6 +48,7 @@ public void setLastShownList(List> list) { lastShownList.clear(); @@ -62,7 +64,6 @@ public void clearLastShownList() { lastShownList.clear(); } - @Override public void commit() { versionedPlanner.commit(); @@ -129,6 +130,11 @@ public Map> getSlots(Set tags return versionedPlanner.getSlots(tags); } + @Override + public boolean slotExists(LocalDate date, ReadOnlySlot slot) { + return getDay(date).contains(slot); + } + @Override public boolean canUndo() { return versionedPlanner.canUndo(); @@ -166,4 +172,10 @@ public boolean equals(Object obj) { return versionedPlanner.equals(other.versionedPlanner) && lastShownList.equals(other.lastShownList); } + + @Override + public int hashCode() { + return Objects.hash(versionedPlanner, lastShownList); + } + } diff --git a/src/planmysem/model/Planner.java b/src/planmysem/model/Planner.java index 5239ef140..996654906 100644 --- a/src/planmysem/model/Planner.java +++ b/src/planmysem/model/Planner.java @@ -85,14 +85,6 @@ public void setDays(HashMap days) { this.semester.setDays(days); } - public HashMap getDays() { - return semester.getDays(); - } - - public Day getDay(LocalDate date) { - return getDays().get(date); - } - public Map> getSlots(Set tags) { final Map> selectedSlots = new TreeMap<>(); @@ -107,6 +99,11 @@ public Map> getSlots(Set tags return selectedSlots; } + @Override + public HashMap getDays() { + return semester.getDays(); + } + @Override public boolean equals(Object other) { return other == this // short circuit if same object diff --git a/src/planmysem/model/VersionedPlanner.java b/src/planmysem/model/VersionedPlanner.java index f68ac7415..9ee8aa995 100644 --- a/src/planmysem/model/VersionedPlanner.java +++ b/src/planmysem/model/VersionedPlanner.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * {@code Planner} that keeps track of its own history. @@ -89,6 +90,11 @@ public boolean equals(Object other) { && currentStatePointer == otherVersionedPlanner.currentStatePointer; } + @Override + public int hashCode() { + return Objects.hash(plannerListState, currentStatePointer); + } + /** * Thrown when trying to {@code undo()} but can't. */ diff --git a/src/planmysem/model/recurrence/Recurrence.java b/src/planmysem/model/recurrence/Recurrence.java index 8f73a1629..c148a54d7 100644 --- a/src/planmysem/model/recurrence/Recurrence.java +++ b/src/planmysem/model/recurrence/Recurrence.java @@ -5,6 +5,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; @@ -173,22 +174,6 @@ public boolean equals(Object other) { @Override public int hashCode() { - int hashCode = 0; - if (recess) { - hashCode += 1; // 0001 - } - if (reading) { - hashCode += 2; // 0010 - } - if (normal) { - hashCode += 4; // 0100 - } - if (exam) { - hashCode += 8; // 1000 - } - if (past) { - hashCode += 16; // 1 0000 - } - return hashCode + day.hashCode() + date.hashCode(); + return Objects.hash(recess, reading, normal, exam, past, date); } } diff --git a/src/planmysem/model/semester/Day.java b/src/planmysem/model/semester/Day.java index 7fcc49991..da89aac10 100644 --- a/src/planmysem/model/semester/Day.java +++ b/src/planmysem/model/semester/Day.java @@ -2,6 +2,7 @@ import java.time.DayOfWeek; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import planmysem.model.slot.ReadOnlySlot; @@ -32,7 +33,7 @@ public Day(DayOfWeek dayOfWeek, String weekType) { this.type = weekType; } - public Day(DayOfWeek dayOfWeek, String weekType, ArrayList slots) { + public Day(DayOfWeek dayOfWeek, String weekType, List slots) { this.dayOfWeek = dayOfWeek; this.type = weekType; @@ -98,11 +99,4 @@ public int hashCode() { // use this method for custom fields hashing instead of implementing your own return Objects.hash(dayOfWeek, type, slots); } - - /** - * Signals that an operation targeting a specified slot in the list would fail because - * there is no such matching slot in the list. - */ - public static class SlotNotFoundException extends Exception { - } } diff --git a/src/planmysem/model/semester/Semester.java b/src/planmysem/model/semester/Semester.java index 8238788d1..fe3e96c24 100644 --- a/src/planmysem/model/semester/Semester.java +++ b/src/planmysem/model/semester/Semester.java @@ -38,17 +38,6 @@ public class Semester implements ReadOnlySemester { private final Set normalDays = new HashSet<>(); private final Set examDays = new HashSet<>(); - /** - * Constructs empty semester. - */ - public Semester() { - this.name = null; - this.academicYear = null; - this.startDate = null; - this.endDate = null; - this.noOfWeeks = 0; - } - /** * Constructs a semester with the given Days. */ @@ -107,7 +96,7 @@ public static Semester generateSemester(LocalDate currentDate) { Set normalDays = new HashSet<>(); Set examDays = new HashSet<>(); - acadCalMap = generateAcadCalMap(currentDate); + acadCalMap = generateAcademicCalMap(currentDate); acadCal = acadCalMap; semesterDetails = getSemesterDetails(currentDate, acadCalMap); acadSem = semesterDetails[1]; @@ -148,7 +137,7 @@ public static Semester generateSemester(LocalDate currentDate) { * @param date used to determine academic year * @return details of academic calendar */ - private static HashMap generateAcadCalMap(LocalDate date) { + private static HashMap generateAcademicCalMap(LocalDate date) { HashMap acadCalMap = new HashMap<>(); LocalDate semOneStartDate = date; LocalDate semTwoEndDate = date; diff --git a/src/planmysem/model/slot/Slot.java b/src/planmysem/model/slot/Slot.java index 5f7ffa4ab..68c4ceee0 100644 --- a/src/planmysem/model/slot/Slot.java +++ b/src/planmysem/model/slot/Slot.java @@ -97,6 +97,17 @@ public void setStartTime(LocalTime value) { startTime = value; } + /** + * Replaces this slot's tags with the tags in {@code replacement}. + */ + public void setTags(Set tags) { + if (tags == null) { + return; + } + this.tags.clear(); + this.tags.addAll(tags); + } + /** * Set duration. */ @@ -134,17 +145,6 @@ public Set getTags() { return tags; } - /** - * Replaces this slot's tags with the tags in {@code replacement}. - */ - public void setTags(Set tags) { - if (tags == null) { - return; - } - this.tags.clear(); - this.tags.addAll(tags); - } - @Override public boolean equals(Object other) { return other == this // short circuit if same object diff --git a/src/planmysem/ui/Formatter.java b/src/planmysem/ui/Formatter.java index df79dd303..5c868f277 100644 --- a/src/planmysem/ui/Formatter.java +++ b/src/planmysem/ui/Formatter.java @@ -1,7 +1,6 @@ package planmysem.ui; import java.time.LocalDate; -import java.util.List; import java.util.Map; import javafx.util.Pair; @@ -24,40 +23,6 @@ public class Formatter { */ private static final String LS = System.lineSeparator(); - - /** - * Format of indexed list item - */ - private static final String MESSAGE_INDEXED_LIST_ITEM = "\t%1$d. %2$s"; - - - /** - * Offset required to convert between 1-indexing and 0-indexing. - */ - private static final int DISPLAYED_INDEX_OFFSET = 1; - - /** - * Formats a list of strings as an indexed list. - */ - private static String asIndexedList(List listItems) { - final StringBuilder formatted = new StringBuilder(); - int displayIndex = 0 + DISPLAYED_INDEX_OFFSET; - for (String listItem : listItems) { - formatted.append(getIndexedListItem(displayIndex, listItem)).append("\n"); - displayIndex++; - } - return formatted.toString(); - } - - /** - * Formats a string as an indexed list item. - * - * @param visibleIndex index for this listing - */ - private static String getIndexedListItem(int visibleIndex, String listItem) { - return String.format(MESSAGE_INDEXED_LIST_ITEM, visibleIndex, listItem); - } - /** * Formats the given strings for displaying to the user. */ @@ -73,13 +38,6 @@ public String format(String... messages) { * Formats the given list of slots for displaying to the user. */ public String formatSlots(Map> slots) { - // final List formattedSlots = new ArrayList<>(); - // - // for (Map.Entry> entry : slots.entrySet()) { - // formattedSlots.add(pair.getKey().toString() + ": " + pair.getValue().toString()); - // } - // - // return format(asIndexedList(formattedSlots)); return Messages.craftListMessage(slots); } diff --git a/src/planmysem/ui/Gui.java b/src/planmysem/ui/Gui.java index fba5c9f73..fd8c0047b 100644 --- a/src/planmysem/ui/Gui.java +++ b/src/planmysem/ui/Gui.java @@ -13,12 +13,7 @@ */ public class Gui implements Ui { - /** - * Offset required to convert between 1-indexing and 0-indexing. - */ - public static final int DISPLAYED_INDEX_OFFSET = 1; - - public static final int INITIAL_WINDOW_WIDTH = 1000; + public static final int INITIAL_WINDOW_WIDTH = 1100; public static final int INITIAL_WINDOW_HEIGHT = 600; private final LogicManager logicManager; diff --git a/src/planmysem/ui/MainWindow.java b/src/planmysem/ui/MainWindow.java index b283dd876..7cca48664 100644 --- a/src/planmysem/ui/MainWindow.java +++ b/src/planmysem/ui/MainWindow.java @@ -63,7 +63,7 @@ private void exitApp() throws Exception { * Returns true of the result given is the result of an exit command */ private boolean isExitCommand(CommandResult result) { - return result.feedbackToUser.equals(ExitCommand.MESSAGE_EXIT_ACKNOWEDGEMENT); + return result.feedbackToUser.equals(ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT); } /** diff --git a/test/data/StorageFileTest/InvalidData.txt b/test/data/StorageFileTest/InvalidData.txt deleted file mode 100644 index 206e95798..000000000 --- a/test/data/StorageFileTest/InvalidData.txt +++ /dev/null @@ -1,6 +0,0 @@ - - - - data - - diff --git a/test/data/StorageFileTest/ValidData.txt b/test/data/StorageFileTest/ValidData.txt deleted file mode 100644 index b0bfb777b..000000000 --- a/test/data/StorageFileTest/ValidData.txt +++ /dev/null @@ -1,956 +0,0 @@ - - - - Sem 2 - AY2018/2019 - 2019-01-14 - 2019-05-12 - 17 - - - 2019-02-09 - - SATURDAY - Week 4 - - - - 2019-02-08 - - FRIDAY - Week 4 - - - - 2019-02-07 - - THURSDAY - Week 4 - - - - 2019-02-06 - - WEDNESDAY - Week 4 - - - - 2019-02-05 - - TUESDAY - Week 4 - - - - 2019-02-04 - - MONDAY - Week 4 - - - - 2019-02-03 - - SUNDAY - Week 3 - - - - 2019-02-02 - - SATURDAY - Week 3 - - - - 2019-02-01 - - FRIDAY - Week 3 - - - - 2019-01-31 - - THURSDAY - Week 3 - - - - 2019-01-30 - - WEDNESDAY - Week 3 - - - - 2019-04-30 - - TUESDAY - Examination Week - - - - 2019-04-20 - - SATURDAY - Week 13 - - - - 2019-04-21 - - SUNDAY - Week 13 - - - - 2019-04-22 - - MONDAY - Reading Week - - - - 2019-04-23 - - TUESDAY - Reading Week - - - - 2019-04-24 - - WEDNESDAY - Reading Week - - - - 2019-04-25 - - THURSDAY - Reading Week - - - - 2019-04-26 - - FRIDAY - Reading Week - - - - 2019-04-27 - - SATURDAY - Reading Week - - - - 2019-04-28 - - SUNDAY - Reading Week - - - - 2019-04-29 - - MONDAY - Examination Week - - - - 2019-02-19 - - TUESDAY - Week 6 - - - - 2019-02-18 - - MONDAY - Week 6 - - - - 2019-02-17 - - SUNDAY - Week 5 - - - - 2019-02-16 - - SATURDAY - Week 5 - - - - 2019-02-15 - - FRIDAY - Week 5 - - - - 2019-02-14 - - THURSDAY - Week 5 - - - - 2019-02-13 - - WEDNESDAY - Week 5 - - - - 2019-02-12 - - TUESDAY - Week 5 - - - - 2019-02-11 - - MONDAY - Week 5 - - - - 2019-02-10 - - SUNDAY - Week 4 - - - - 2019-05-01 - - WEDNESDAY - Examination Week - - - - 2019-05-02 - - THURSDAY - Examination Week - - - - 2019-05-03 - - FRIDAY - Examination Week - - - - 2019-05-04 - - SATURDAY - Examination Week - - - - 2019-05-05 - - SUNDAY - Examination Week - - - - 2019-05-06 - - MONDAY - Examination Week - - - - 2019-05-07 - - TUESDAY - Examination Week - - - - 2019-05-08 - - WEDNESDAY - Examination Week - - - - 2019-05-09 - - THURSDAY - Examination Week - - - - 2019-02-28 - - THURSDAY - Recess Week - - - - 2019-02-27 - - WEDNESDAY - Recess Week - - - - 2019-02-26 - - TUESDAY - Recess Week - - - - 2019-02-25 - - MONDAY - Recess Week - - - - 2019-02-24 - - SUNDAY - Week 6 - - - - 2019-02-23 - - SATURDAY - Week 6 - - - - 2019-02-22 - - FRIDAY - Week 6 - - - - 2019-02-21 - - THURSDAY - Week 6 - - - - 2019-02-20 - - WEDNESDAY - Week 6 - - - - 2019-05-10 - - FRIDAY - Examination Week - - - - 2019-05-11 - - SATURDAY - Examination Week - - - - 2019-03-01 - - FRIDAY - Recess Week - - - - 2019-03-02 - - SATURDAY - Recess Week - - - - 2019-03-03 - - SUNDAY - Recess Week - - - - 2019-03-04 - - MONDAY - Week 7 - - - - 2019-03-05 - - TUESDAY - Week 7 - - - - 2019-03-06 - - WEDNESDAY - Week 7 - - - - 2019-03-07 - - THURSDAY - Week 7 - - - - 2019-03-08 - - FRIDAY - Week 7 - - - - 2019-03-09 - - SATURDAY - Week 7 - - - - 2019-03-10 - - SUNDAY - Week 7 - - - - 2019-03-11 - - MONDAY - Week 8 - - - - 2019-03-12 - - TUESDAY - Week 8 - - - - 2019-03-13 - - WEDNESDAY - Week 8 - - - - 2019-03-14 - - THURSDAY - Week 8 - - - - 2019-03-15 - - FRIDAY - Week 8 - - - - 2019-03-16 - - SATURDAY - Week 8 - - - - 2019-03-17 - - SUNDAY - Week 8 - - - - 2019-03-18 - - MONDAY - Week 9 - - - - 2019-03-19 - - TUESDAY - Week 9 - - - - 2019-03-20 - - WEDNESDAY - Week 9 - - - - 2019-03-21 - - THURSDAY - Week 9 - - - - 2019-03-22 - - FRIDAY - Week 9 - - - - 2019-03-23 - - SATURDAY - Week 9 - - - - 2019-03-24 - - SUNDAY - Week 9 - - - - 2019-03-25 - - MONDAY - Week 10 - - - - 2019-03-26 - - TUESDAY - Week 10 - - - - 2019-03-27 - - WEDNESDAY - Week 10 - - - - 2019-03-28 - - THURSDAY - Week 10 - - - - 2019-03-29 - - FRIDAY - Week 10 - - - - 2019-01-19 - - SATURDAY - Week 1 - - - - 2019-01-18 - - FRIDAY - Week 1 - - - - 2019-01-17 - - THURSDAY - Week 1 - - - - 2019-01-16 - - WEDNESDAY - Week 1 - - - - 2019-01-15 - - TUESDAY - Week 1 - - - - 2019-01-14 - - MONDAY - Week 1 - - - - 2019-03-30 - - SATURDAY - Week 10 - - - - 2019-03-31 - - SUNDAY - Week 10 - - - - 2019-04-01 - - MONDAY - Week 11 - - - - 2019-04-02 - - TUESDAY - Week 11 - - - - 2019-04-03 - - WEDNESDAY - Week 11 - - - - 2019-04-04 - - THURSDAY - Week 11 - - - - 2019-04-05 - - FRIDAY - Week 11 - - - - 2019-04-06 - - SATURDAY - Week 11 - - - - 2019-04-07 - - SUNDAY - Week 11 - - - - 2019-04-08 - - MONDAY - Week 12 - - - - 2019-04-09 - - TUESDAY - Week 12 - - - - 2019-01-29 - - TUESDAY - Week 3 - - - - 2019-01-28 - - MONDAY - Week 3 - - - - 2019-01-27 - - SUNDAY - Week 2 - - - - 2019-01-26 - - SATURDAY - Week 2 - - - - 2019-01-25 - - FRIDAY - Week 2 - - - - 2019-01-24 - - THURSDAY - Week 2 - - - - 2019-01-23 - - WEDNESDAY - Week 2 - - - - 2019-01-22 - - TUESDAY - Week 2 - - - - 2019-01-21 - - MONDAY - Week 2 - - - - 2019-01-20 - - SUNDAY - Week 1 - - - - 2019-04-10 - - WEDNESDAY - Week 12 - - - - 2019-04-11 - - THURSDAY - Week 12 - - - - 2019-04-12 - - FRIDAY - Week 12 - - - - 2019-04-13 - - SATURDAY - Week 12 - - - - 2019-04-14 - - SUNDAY - Week 12 - - - - 2019-04-15 - - MONDAY - Week 13 - - - - 2019-04-16 - - TUESDAY - Week 13 - - - - 2019-04-17 - - WEDNESDAY - Week 13 - - - - 2019-04-18 - - THURSDAY - Week 13 - - - - 2019-04-19 - - FRIDAY - Week 13 - - - - 2019-03-01 - 2019-02-28 - 2019-03-02 - 2019-02-27 - 2019-03-03 - 2019-02-26 - 2019-02-25 - 2019-04-22 - 2019-04-23 - 2019-04-24 - 2019-04-25 - 2019-04-26 - 2019-04-27 - 2019-04-28 - 2019-02-09 - 2019-02-08 - 2019-02-07 - 2019-02-06 - 2019-02-05 - 2019-02-04 - 2019-02-03 - 2019-02-02 - 2019-02-01 - 2019-01-31 - 2019-01-30 - 2019-04-20 - 2019-04-21 - 2019-03-10 - 2019-03-11 - 2019-03-12 - 2019-03-13 - 2019-03-14 - 2019-03-15 - 2019-03-16 - 2019-03-17 - 2019-03-18 - 2019-03-19 - 2019-02-19 - 2019-02-18 - 2019-02-17 - 2019-02-16 - 2019-02-15 - 2019-02-14 - 2019-02-13 - 2019-02-12 - 2019-02-11 - 2019-02-10 - 2019-03-20 - 2019-03-21 - 2019-03-22 - 2019-03-23 - 2019-03-24 - 2019-03-25 - 2019-03-26 - 2019-03-27 - 2019-03-28 - 2019-03-29 - 2019-01-19 - 2019-01-18 - 2019-01-17 - 2019-01-16 - 2019-01-15 - 2019-01-14 - 2019-02-24 - 2019-02-23 - 2019-02-22 - 2019-02-21 - 2019-02-20 - 2019-03-30 - 2019-03-31 - 2019-04-01 - 2019-04-02 - 2019-04-03 - 2019-04-04 - 2019-04-05 - 2019-04-06 - 2019-04-07 - 2019-04-08 - 2019-04-09 - 2019-01-29 - 2019-01-28 - 2019-01-27 - 2019-01-26 - 2019-01-25 - 2019-01-24 - 2019-01-23 - 2019-01-22 - 2019-01-21 - 2019-01-20 - 2019-04-10 - 2019-04-11 - 2019-04-12 - 2019-04-13 - 2019-04-14 - 2019-04-15 - 2019-04-16 - 2019-03-04 - 2019-04-17 - 2019-03-05 - 2019-04-18 - 2019-03-06 - 2019-04-19 - 2019-03-07 - 2019-03-08 - 2019-03-09 - 2019-04-30 - 2019-05-10 - 2019-05-11 - 2019-05-01 - 2019-05-02 - 2019-05-03 - 2019-05-04 - 2019-05-05 - 2019-05-06 - 2019-05-07 - 2019-04-29 - 2019-05-08 - 2019-05-09 - - diff --git a/test/java/planmysem/common/UtilsTest.java b/test/java/planmysem/common/UtilsTest.java index 7e511e496..b1ca1f505 100644 --- a/test/java/planmysem/common/UtilsTest.java +++ b/test/java/planmysem/common/UtilsTest.java @@ -2,6 +2,7 @@ import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static planmysem.common.Utils.getDuration; import static planmysem.common.Utils.getEndTime; @@ -10,6 +11,7 @@ import java.time.LocalDate; import java.time.LocalTime; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Before; @@ -45,7 +47,7 @@ public void isAnyNull() { assertTrue(Utils.isAnyNull(new Object(), new Object(), null)); // confirms nulls inside the list are not considered - List nullList = Arrays.asList((Object) null); + List nullList = Collections.singletonList(null); assertFalse(Utils.isAnyNull(nullList)); } @@ -68,8 +70,8 @@ public void elementsAreUnique() { assertNotUnique("abc", "abc"); assertNotUnique("abc", "", "abc", "ABC"); assertNotUnique("", "abc", "a", "abc"); - assertNotUnique(1, Integer.valueOf(1)); - assertNotUnique(null, 1, Integer.valueOf(1)); + assertNotUnique(1, 1); + assertNotUnique(null, 1, 1); assertNotUnique(null, null); assertNotUnique(null, "a", "b", null); } @@ -125,6 +127,7 @@ public void parse_day_unsuccessful() { assertEquals(Utils.parseDay("Fr"), -1); assertEquals(Utils.parseDay("8"), -1); assertEquals(Utils.parseDay("0"), -1); + assertEquals(Utils.parseDay(""), -1); } @Test @@ -138,9 +141,9 @@ public void parse_date_successful() { @Test public void parse_date_unsuccessful() { - assertEquals(Utils.parseDate("00-06-2019"), null); - assertEquals(Utils.parseDate("01-13-2019"), null); - assertEquals(Utils.parseDate("32-12-2019"), null); + assertNull(Utils.parseDate("00-06-2019")); + assertNull(Utils.parseDate("01-13-2019")); + assertNull(Utils.parseDate("v")); } @Test @@ -152,14 +155,14 @@ public void parse_time_successful() { assertEquals(Utils.parseTime("8:00"), LocalTime.of(8, 0)); assertEquals(Utils.parseTime("8:00 AM"), LocalTime.of(8, 0)); assertEquals(Utils.parseTime("8:00 am"), LocalTime.of(8, 0)); - + assertNull(Utils.parseTime(null)); } @Test public void parse_time_unsuccessful() { - assertEquals(Utils.parseTime("14:00 am"), null); - assertEquals(Utils.parseTime("16:00 pm"), null); - assertEquals(Utils.parseTime("24:00"), null); + assertNull(Utils.parseTime("14:00 am")); + assertNull(Utils.parseTime("16:00 pm")); + assertNull(Utils.parseTime("24:00")); } @Test @@ -174,6 +177,7 @@ public void parse_integer_successful() { @Test public void parse_integer_unsuccessful() { + assertEquals(Utils.parseInteger("120000000000000"), -1); assertEquals(Utils.parseInteger("12 0"), -1); assertEquals(Utils.parseInteger("0.1"), -1); assertEquals(Utils.parseInteger("test"), -1); @@ -181,7 +185,7 @@ public void parse_integer_unsuccessful() { } @Test - public void parse_get_duration_successful() { + public void parse_getDuration_successful() { LocalTime startTime = LocalTime.now(Clock.get()); LocalTime endTime = startTime.plusMinutes(60); @@ -189,7 +193,7 @@ public void parse_get_duration_successful() { } @Test - public void parse_get_end_time_successful() { + public void parse_getEndTime_successful() { LocalTime startTime = LocalTime.now(Clock.get()); LocalTime endTime = startTime.plusMinutes(60); @@ -197,7 +201,7 @@ public void parse_get_end_time_successful() { } @Test - public void parse_get_nearest_day_of_week_successful() { + public void parse_getNearestDayOfWeek_successful() { LocalDate date = LocalDate.of(2019, 1, 1); LocalDate nearestMonday = LocalDate.of(2019, 1, 7); diff --git a/test/java/planmysem/logic/Commands/AddCommandTest.java b/test/java/planmysem/logic/Commands/AddCommandTest.java index 4ab424223..e1798d082 100644 --- a/test/java/planmysem/logic/Commands/AddCommandTest.java +++ b/test/java/planmysem/logic/Commands/AddCommandTest.java @@ -1,8 +1,6 @@ package planmysem.logic.Commands; -import static java.util.Objects.requireNonNull; -import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static planmysem.logic.commands.AddCommand.MESSAGE_SUCCESS; import static planmysem.logic.commands.AddCommand.craftSuccessMessage; @@ -37,15 +35,15 @@ import planmysem.model.slot.Slot; import planmysem.testutil.SlotBuilder; + public class AddCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); private static final CommandHistory EMPTY_COMMAND_HISTORY = new CommandHistory(); private CommandHistory commandHistory = new CommandHistory(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Before public void setup() { Clock.set("2019-01-14T10:00:00Z"); @@ -80,7 +78,7 @@ public void execute_slotAcceptedByModel_addSuccessful() throws CommandException } @Test - public void execute_InvalidDate_throwsCommandException() throws Exception { + public void execute_invalidDate_throwsCommandException() throws Exception { ModelStubNeverSlotAdded modelStub = new ModelStubNeverSlotAdded(); Slot validSlot = new SlotBuilder().slotOne(); Recurrence validRecurrence = new SlotBuilder().recurrenceOne(); @@ -93,29 +91,29 @@ public void execute_InvalidDate_throwsCommandException() throws Exception { } @Test - public void equals() throws Exception { + public void equals() { Slot slot1 = new SlotBuilder().generateSlot(1); Recurrence recurrence = new SlotBuilder().recurrenceOne(); AddCommand addCommand1 = new AddCommand(slot1, recurrence); // same object -> returns true - assertTrue(addCommand1.equals(addCommand1)); + assertEquals(addCommand1, addCommand1); // same values -> returns true AddCommand addCommand1Copy = new AddCommand(slot1, recurrence); - assertTrue(addCommand1.equals(addCommand1Copy)); + assertEquals(addCommand1, addCommand1Copy); // different types -> returns false - assertFalse(addCommand1.equals(1)); + assertNotEquals(addCommand1, 1); // null -> returns false - assertFalse(addCommand1.equals(null)); + assertNotEquals(addCommand1, null); // different command -> returns false Slot slot2 = new SlotBuilder().generateSlot(2); AddCommand addCommand2 = new AddCommand(slot2, recurrence); - assertFalse(addCommand1.equals(addCommand2)); + assertNotEquals(addCommand1, addCommand2); } @@ -129,22 +127,22 @@ public List>> getLastShownList() } @Override - public void clearLastShownList() { + public void setLastShownList(List>> list) { throw new AssertionError("This method should not be called."); } @Override - public void commit() { + public void setLastShownList(Map> list) { + throw new AssertionError("This method should not be called."); } @Override - public void setLastShownList(List>> list) { + public void clearLastShownList() { throw new AssertionError("This method should not be called."); } @Override - public void setLastShownList(Map> list) { - throw new AssertionError("This method should not be called."); + public void commit() { } @Override @@ -152,6 +150,11 @@ public Pair> getLastShownItem(int ind throw new AssertionError("This method should not be called."); } + @Override + public boolean slotExists(LocalDate date, ReadOnlySlot slot) { + throw new AssertionError("This method should not be called."); + } + @Override public Day addSlot(LocalDate date, Slot slot) throws Semester.DateNotFoundException { throw new AssertionError("This method should not be called."); @@ -225,23 +228,11 @@ public boolean equals(Object obj) { } } - /** - * A Model stub that contains a single slot. - */ - private class ModelStubWithSlot extends ModelStub { - private final Slot slot; - - ModelStubWithSlot(Slot slot) { - requireNonNull(slot); - this.slot = slot; - } - } - /** * A Model stub that always accept the slot being added. */ private class ModelStubAcceptingSlotAdded extends ModelStub { - Map days = new TreeMap<>(); + private Map days = new TreeMap<>(); @Override public Day addSlot(LocalDate date, Slot slot) { @@ -274,6 +265,4 @@ public Planner getPlanner() { return new Planner(); } } - - } diff --git a/test/java/planmysem/logic/Commands/ClearCommandTest.java b/test/java/planmysem/logic/Commands/ClearCommandTest.java index f64b79160..f087234ea 100644 --- a/test/java/planmysem/logic/Commands/ClearCommandTest.java +++ b/test/java/planmysem/logic/Commands/ClearCommandTest.java @@ -8,6 +8,7 @@ import org.junit.Before; import org.junit.Test; + import planmysem.common.Clock; import planmysem.logic.CommandHistory; import planmysem.logic.commands.ClearCommand; diff --git a/test/java/planmysem/logic/Commands/CommandResultTest.java b/test/java/planmysem/logic/Commands/CommandResultTest.java new file mode 100644 index 000000000..885ab9d98 --- /dev/null +++ b/test/java/planmysem/logic/Commands/CommandResultTest.java @@ -0,0 +1,26 @@ +package planmysem.logic.Commands; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import org.junit.Test; +import planmysem.logic.commands.CommandResult; + +public class CommandResultTest { + @Test + public void equals() { + CommandResult commandResult = new CommandResult("test"); + CommandResult CommandResultClone = new CommandResult("test"); + + // equals same object + assertEquals(commandResult, commandResult); + assertEquals(commandResult.hashCode(), commandResult.hashCode()); + + // equals null + assertNotEquals(commandResult, null); + + // equals different object same values + assertEquals(commandResult, CommandResultClone); + assertEquals(commandResult.hashCode(), CommandResultClone.hashCode()); + } +} diff --git a/test/java/planmysem/logic/Commands/CommandTestUtil.java b/test/java/planmysem/logic/Commands/CommandTestUtil.java index 0272c6807..1766b37da 100644 --- a/test/java/planmysem/logic/Commands/CommandTestUtil.java +++ b/test/java/planmysem/logic/Commands/CommandTestUtil.java @@ -19,50 +19,7 @@ /** * Contains helper methods for testing commands. */ -public class CommandTestUtil { - - // public static final String VALID_NAME_AMY = "Amy Bee"; - // public static final String VALID_NAME_BOB = "Bob Choo"; - // public static final String VALID_PHONE_AMY = "11111111"; - // public static final String VALID_PHONE_BOB = "22222222"; - // public static final String VALID_EMAIL_AMY = "amy@example.com"; - // public static final String VALID_EMAIL_BOB = "bob@example.com"; - // public static final String VALID_ADDRESS_AMY = "Block 312, Amy Street 1"; - // public static final String VALID_ADDRESS_BOB = "Block 123, Bobby Street 3"; - // public static final String VALID_TAG_HUSBAND = "husband"; - // public static final String VALID_TAG_FRIEND = "friend"; - - // public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY; - // public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB; - // public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY; - // public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB; - // public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY; - // public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB; - // public static final String ADDRESS_DESC_AMY = " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY; - // public static final String ADDRESS_DESC_BOB = " " + PREFIX_ADDRESS + VALID_ADDRESS_BOB; - // public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND; - // public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND; - // - // public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names - // public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones - // public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol - // public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses - // public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags - - // public static final String PREAMBLE_WHITESPACE = "\t \r \n"; - // public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble"; - - // public static final EditCommand.EditPersonDescriptor DESC_AMY; - // public static final EditCommand.EditPersonDescriptor DESC_BOB; - - // static { - // DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY) - // .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) - // .withTags(VALID_TAG_FRIEND).build(); - // DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB) - // .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) - // .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); - // } +class CommandTestUtil { /** * Executes the given {@code command}, confirms that
@@ -70,7 +27,7 @@ public class CommandTestUtil { * - the {@code actualModel} matches {@code expectedModel}
* - the {@code actualCommandHistory} remains unchanged. */ - public static void assertCommandSuccess(Command command, Model actualModel, CommandHistory actualCommandHistory, + static void assertCommandSuccess(Command command, Model actualModel, CommandHistory actualCommandHistory, CommandResult expectedCommandResult, Model expectedModel) { CommandHistory expectedCommandHistory = new CommandHistory(actualCommandHistory); try { @@ -87,7 +44,7 @@ public static void assertCommandSuccess(Command command, Model actualModel, Comm * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandHistory, CommandResult, Model)} * that takes a string {@code expectedMessage}. */ - public static void assertCommandSuccess(Command command, Model actualModel, CommandHistory actualCommandHistory, + static void assertCommandSuccess(Command command, Model actualModel, CommandHistory actualCommandHistory, String expectedMessage, Model expectedModel) { CommandResult expectedCommandResult = new CommandResult(expectedMessage); assertCommandSuccess(command, actualModel, actualCommandHistory, expectedCommandResult, expectedModel); @@ -99,48 +56,24 @@ public static void assertCommandSuccess(Command command, Model actualModel, Comm * - the CommandException message matches {@code expectedMessage}
* - the planner, last shown list in {@code actualModel} remain unchanged
* - {@code actualCommandHistory} remains unchanged. - */ - public static void assertCommandFailure(Command command, Model actualModel, CommandHistory actualCommandHistory, - String expectedMessage) { - Planner expectedPlanner = new Planner(actualModel.getPlanner()); - actualModel.getDays(); - List>> expectedLastShownList = new ArrayList<>(actualModel.getLastShownList()); + */ + static void assertCommandFailure(Command command, Model actualModel, CommandHistory actualCommandHistory, + String expectedMessage) { + Planner expectedPlanner = new Planner(actualModel.getPlanner()); + actualModel.getDays(); + List>> expectedLastShownList = + new ArrayList<>(actualModel.getLastShownList()); - CommandHistory expectedCommandHistory = new CommandHistory(actualCommandHistory); + CommandHistory expectedCommandHistory = new CommandHistory(actualCommandHistory); - try { - command.execute(actualModel, actualCommandHistory); - throw new AssertionError("The expected CommandException was not thrown."); - } catch (CommandException e) { - assertEquals(expectedMessage, e.getMessage()); - assertEquals(expectedPlanner, actualModel.getPlanner()); - assertEquals(expectedLastShownList, actualModel.getLastShownList()); -// assertEquals(expectedSelectedPerson, actualModel.getSelectedPerson()); - assertEquals(expectedCommandHistory, actualCommandHistory); - } + try { + command.execute(actualModel, actualCommandHistory); + throw new AssertionError("The expected CommandException was not thrown."); + } catch (CommandException e) { + assertEquals(expectedMessage, e.getMessage()); + assertEquals(expectedPlanner, actualModel.getPlanner()); + assertEquals(expectedLastShownList, actualModel.getLastShownList()); + assertEquals(expectedCommandHistory, actualCommandHistory); } - - // /** - // * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the - // * {@code model}'s address book. - // */ - // public static void showPersonAtIndex(Model model, Index targetIndex) { - // assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size()); - // - // Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased()); - // final String[] splitName = person.getName().fullName.split("\\s+"); - // model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0]))); - // - // assertEquals(1, model.getFilteredPersonList().size()); - // } - // - // /** - // * Deletes the first person in {@code model}'s filtered list from {@code model}'s address book. - // */ - // public static void deleteFirstPerson(Model model) { - // Person firstPerson = model.getFilteredPersonList().get(0); - // model.deletePerson(firstPerson); - // model.commitAddressBook(); - // } - + } } diff --git a/test/java/planmysem/logic/Commands/DeleteCommandTest.java b/test/java/planmysem/logic/Commands/DeleteCommandTest.java index c7522e594..dd59d5ef6 100644 --- a/test/java/planmysem/logic/Commands/DeleteCommandTest.java +++ b/test/java/planmysem/logic/Commands/DeleteCommandTest.java @@ -1,9 +1,11 @@ package planmysem.logic.Commands; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static planmysem.common.Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX; import static planmysem.logic.Commands.CommandTestUtil.assertCommandFailure; import static planmysem.logic.Commands.CommandTestUtil.assertCommandSuccess; +import static planmysem.logic.commands.DeleteCommand.MESSAGE_SLOT_NOT_IN_PLANNER; import static planmysem.logic.commands.DeleteCommand.MESSAGE_SUCCESS; import static planmysem.logic.commands.DeleteCommand.MESSAGE_SUCCESS_NO_CHANGE; @@ -31,6 +33,9 @@ import planmysem.testutil.SlotBuilder; public class DeleteCommandTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); private Model model; private Model expectedModel; private Pair> pair1; @@ -38,12 +43,8 @@ public class DeleteCommandTest { private Pair> pair3; private Pair> pair4; private CommandHistory commandHistory = new CommandHistory(); - private SlotBuilder slotBuilder = new SlotBuilder(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Before public void setup() throws Exception { Clock.set("2019-01-14T10:00:00Z"); @@ -154,7 +155,7 @@ public void execute_validIndex_success() { } @Test - public void execute_InvalidTag_throwsCommandException() { + public void execute_invalidTag_throwsCommandException() { Set tags = pair4.getValue().getValue().getTags(); DeleteCommand deleteCommand = new DeleteCommand(tags); @@ -169,10 +170,21 @@ public void execute_InvalidTag_throwsCommandException() { } @Test - public void execute_InvalidIndex_throwsCommandException() { - DeleteCommand deleteCommand = new DeleteCommand(5); + public void execute_invalidSlot_throwsCommandException() { + DeleteCommand deleteCommand = new DeleteCommand(1); - String expectedMessage = Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX; + String expectedMessage = MESSAGE_SLOT_NOT_IN_PLANNER; + + // removed slots with of index 1 in lastShownSlot, so the exception will occur + model.removeSlot(pair4); + + assertCommandFailure(deleteCommand, model, commandHistory, expectedMessage); + } + + @Test + public void execute_invalidIndex_throwsCommandException() { + DeleteCommand deleteCommand = new DeleteCommand(5); + String expectedMessage = MESSAGE_INVALID_SLOT_DISPLAYED_INDEX; assertCommandFailure(deleteCommand, model, commandHistory, expectedMessage); } @@ -182,20 +194,20 @@ public void equals() { DeleteCommand deleteFirstCommand = new DeleteCommand(1); // same object -> returns true - assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); + assertEquals(deleteFirstCommand, deleteFirstCommand); // same values -> returns true DeleteCommand deleteFirstCommandCopy = new DeleteCommand(1); - assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); + assertEquals(deleteFirstCommand, deleteFirstCommandCopy); // different types -> returns false - assertFalse(deleteFirstCommand.equals(1)); + assertNotEquals(deleteFirstCommand, 1); // null -> returns false - assertFalse(deleteFirstCommand.equals(null)); + assertNotEquals(deleteFirstCommand, null); // different command -> returns false DeleteCommand deleteSecondCommand = new DeleteCommand(2); - assertFalse(deleteFirstCommand.equals(deleteSecondCommand)); + assertNotEquals(deleteFirstCommand, deleteSecondCommand); } } diff --git a/test/java/planmysem/logic/Commands/EditCommandTest.java b/test/java/planmysem/logic/Commands/EditCommandTest.java index e6ab2f8a4..5552c2020 100644 --- a/test/java/planmysem/logic/Commands/EditCommandTest.java +++ b/test/java/planmysem/logic/Commands/EditCommandTest.java @@ -1,7 +1,7 @@ package planmysem.logic.Commands; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static planmysem.logic.Commands.CommandTestUtil.assertCommandFailure; import static planmysem.logic.Commands.CommandTestUtil.assertCommandSuccess; import static planmysem.logic.commands.EditCommand.MESSAGE_SUCCESS; @@ -10,7 +10,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; -import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -33,6 +33,8 @@ import planmysem.testutil.SlotBuilder; public class EditCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); private Model model; private Model expectedModel; private Pair> pair1; @@ -40,12 +42,8 @@ public class EditCommandTest { private Pair> pair3; private Pair> pair4; private CommandHistory commandHistory = new CommandHistory(); - private SlotBuilder slotBuilder = new SlotBuilder(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Before public void setup() throws Exception { Clock.set("2019-01-14T10:00:00Z"); @@ -126,7 +124,7 @@ public void execute_validTag_success() { String description = "new description"; LocalTime startTime = LocalTime.of(8, 0); int duration = 60; - Set tags = new HashSet<>(Arrays.asList("tag1")); + Set tags = new HashSet<>(Collections.singletonList("tag1")); EditCommand editCommand = new EditCommand( name, @@ -172,8 +170,8 @@ public void execute_validTag_success() { } @Test - public void execute_InvalidTag_throwsCommandException() { - Set selectTags = new HashSet<>(Arrays.asList("tag does not exist")); + public void execute_invalidTag_throwsCommandException() { + Set selectTags = new HashSet<>(Collections.singletonList("tag does not exist")); // values to edit String name = "new name"; @@ -181,7 +179,7 @@ public void execute_InvalidTag_throwsCommandException() { String description = "new description"; LocalTime startTime = LocalTime.of(8, 0); int duration = 60; - Set tags = new HashSet<>(Arrays.asList("tag1")); + Set tags = new HashSet<>(Collections.singletonList("tag1")); EditCommand editCommand = new EditCommand( name, @@ -200,7 +198,7 @@ public void execute_InvalidTag_throwsCommandException() { } @Test - public void execute_InvalidIndex_throwsCommandException() { + public void execute_invalidIndex_throwsCommandException() { // values to edit String name = "new name"; String location = "new location"; @@ -208,7 +206,7 @@ public void execute_InvalidIndex_throwsCommandException() { LocalDate date = LocalDate.of(2019, 2, 2); LocalTime startTime = LocalTime.of(8, 0); int duration = 60; - Set tags = new HashSet<>(Arrays.asList("tag1")); + Set tags = new HashSet<>(Collections.singletonList("tag1")); EditCommand editCommand = new EditCommand( 5, @@ -239,11 +237,59 @@ public void execute_validIndex_success() { LocalDate date = LocalDate.of(2019, 2, 2); LocalTime startTime = LocalTime.of(8, 0); int duration = 60; - Set tags = new HashSet<>(Arrays.asList("tag1")); + Set tags = new HashSet<>(Collections.singletonList("tag1")); + + EditCommand editCommand = new EditCommand( + 1, + name, + date, + startTime, + duration, + location, + description, + tags + ); + + String messageSelected = Messages.craftSelectedMessage(1); + String messageSlots = editCommand.craftSuccessMessage(selectedSlots); + + String expectedMessage = String.format(MESSAGE_SUCCESS, selectedSlots.size(), + messageSelected, messageSlots); + + expectedModel.editSlot( + pair1.getKey(), + pair1.getValue().getValue(), + date, + startTime, + duration, + name, + location, + description, + tags + ); + expectedModel.commit(); + + assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); + } + + @Test + public void execute_validIndexEmptyValues_success() { + Map> selectedSlots = new TreeMap<>(); + Pair> slot = model.getLastShownItem(1); + selectedSlots.put(slot.getKey(), slot.getValue()); + + // values to edit + String name = ""; + String location = ""; + String description = ""; + LocalDate date = LocalDate.of(2019, 2, 2); + LocalTime startTime = LocalTime.of(8, 0); + int duration = 60; + Set tags = new HashSet<>(Collections.singletonList("tag1")); EditCommand editCommand = new EditCommand( 1, - "new name", + name, date, startTime, duration, @@ -284,11 +330,11 @@ public void equals() { 60, "location", "description", - new HashSet<>(Arrays.asList("tag1")) + new HashSet<>(Collections.singletonList("tag1")) ); // same object -> returns true - assertTrue(editFirstCommand.equals(editFirstCommand)); + assertEquals(editFirstCommand, editFirstCommand); // same values -> returns true EditCommand editFirstCommandCopy = new EditCommand( @@ -299,15 +345,15 @@ public void equals() { 60, "location", "description", - new HashSet<>(Arrays.asList("tag1")) + new HashSet<>(Collections.singletonList("tag1")) ); - assertTrue(editFirstCommand.equals(editFirstCommandCopy)); + assertEquals(editFirstCommand, editFirstCommandCopy); // different types -> returns false - assertFalse(editFirstCommand.equals(1)); + assertNotEquals(editFirstCommand, 1); // null -> returns false - assertFalse(editFirstCommand.equals(null)); + assertNotEquals(editFirstCommand, null); // different command -> returns false EditCommand deleteSecondCommand = new EditCommand( @@ -318,8 +364,8 @@ public void equals() { 60, "location", "description", - new HashSet<>(Arrays.asList("tag1")) + new HashSet<>(Collections.singletonList("tag1")) ); - assertFalse(editFirstCommand.equals(deleteSecondCommand)); + assertNotEquals(editFirstCommand, deleteSecondCommand); } } diff --git a/test/java/planmysem/logic/Commands/ExitCommandTest.java b/test/java/planmysem/logic/Commands/ExitCommandTest.java index bc43e97d1..13494e65e 100644 --- a/test/java/planmysem/logic/Commands/ExitCommandTest.java +++ b/test/java/planmysem/logic/Commands/ExitCommandTest.java @@ -1,7 +1,7 @@ package planmysem.logic.Commands; import static planmysem.logic.Commands.CommandTestUtil.assertCommandSuccess; -import static planmysem.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWEDGEMENT; +import static planmysem.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT; import org.junit.Test; import planmysem.logic.CommandHistory; @@ -17,7 +17,7 @@ public class ExitCommandTest { @Test public void execute_exit_success() { - CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWEDGEMENT); + CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT); assertCommandSuccess(new ExitCommand(), model, commandHistory, expectedCommandResult, expectedModel); } } diff --git a/test/java/planmysem/logic/Commands/ExportCommandTest.java b/test/java/planmysem/logic/Commands/ExportCommandTest.java index 8a179fb26..745caec06 100644 --- a/test/java/planmysem/logic/Commands/ExportCommandTest.java +++ b/test/java/planmysem/logic/Commands/ExportCommandTest.java @@ -23,7 +23,7 @@ public void setup() { @Test public void execute_export_success() throws IOException { IcsSemester semester = new IcsSemester(model.getPlanner().getSemester()); - String expectedIcs = new String("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nEND:VCALENDAR\r\n"); + String expectedIcs = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nEND:VCALENDAR\r\n"; String actualIcs = semester.toString(); Assert.assertEquals(actualIcs, expectedIcs); } diff --git a/test/java/planmysem/logic/Commands/FindCommandTest.java b/test/java/planmysem/logic/Commands/FindCommandTest.java index f1527bafa..92eb7097b 100644 --- a/test/java/planmysem/logic/Commands/FindCommandTest.java +++ b/test/java/planmysem/logic/Commands/FindCommandTest.java @@ -1,5 +1,24 @@ package planmysem.logic.Commands; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static planmysem.common.Messages.MESSAGE_INVALID_MULTIPLE_PARAMS; +import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS; +import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS_NONE; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.Set; +import java.util.TreeMap; + import javafx.util.Pair; import org.junit.Before; import org.junit.Rule; @@ -22,18 +41,6 @@ import planmysem.model.slot.Slot; import planmysem.testutil.SlotBuilder; -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.util.*; - -import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertFalse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static planmysem.common.Messages.MESSAGE_INVALID_MULTIPLE_PARAMS; -import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS; -import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS_NONE; - public class FindCommandTest { private Model model; private Model expectedModel; @@ -201,7 +208,7 @@ public void isFindByName_NullName_ValidTag() { } @Test - public void execute_slotAcceptedByModel_FindExactNameSuccessful() throws Exception { + public void execute_slotAcceptedByModel_FindExactNameSuccessful() { CommandResult commandResult = new FindCommand(slotBuilder.generateSlot(1).getName(), null).execute(model, commandHistory); List selectedSlots = new ArrayList<>(); @@ -240,7 +247,7 @@ public int compare(WeightedName p1, WeightedName p2) { } @Test - public void execute_slotAcceptedByModel_FindExactTagSuccessful() throws Exception { + public void execute_slotAcceptedByModel_FindExactTagSuccessful() { Set tags = slotBuilder.generateSlot(1).getTags(); String tagToTest = tags.iterator().next(); diff --git a/test/java/planmysem/logic/parser/HelpCommandTest.java b/test/java/planmysem/logic/Commands/HelpCommandTest.java similarity index 95% rename from test/java/planmysem/logic/parser/HelpCommandTest.java rename to test/java/planmysem/logic/Commands/HelpCommandTest.java index ea4ad0b41..a2e8d3bf7 100644 --- a/test/java/planmysem/logic/parser/HelpCommandTest.java +++ b/test/java/planmysem/logic/Commands/HelpCommandTest.java @@ -1,9 +1,10 @@ -package planmysem.logic.parser; +package planmysem.logic.Commands; import static planmysem.logic.Commands.CommandTestUtil.assertCommandSuccess; import static planmysem.logic.commands.HelpCommand.MESSAGE_ALL_USAGES; import org.junit.Test; + import planmysem.logic.CommandHistory; import planmysem.logic.commands.CommandResult; import planmysem.logic.commands.HelpCommand; diff --git a/test/java/planmysem/logic/Commands/ListCommandTest.java b/test/java/planmysem/logic/Commands/ListCommandTest.java index e56eddd09..2cf047aba 100644 --- a/test/java/planmysem/logic/Commands/ListCommandTest.java +++ b/test/java/planmysem/logic/Commands/ListCommandTest.java @@ -1,5 +1,19 @@ package planmysem.logic.Commands; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static planmysem.common.Messages.MESSAGE_INVALID_MULTIPLE_PARAMS; +import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS; +import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS_NONE; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + import javafx.util.Pair; import org.junit.Before; import org.junit.Rule; @@ -12,25 +26,14 @@ import planmysem.logic.commands.ListCommand; import planmysem.logic.parser.ListCommandParser; import planmysem.logic.parser.exceptions.ParseException; -import planmysem.model.*; +import planmysem.model.Model; +import planmysem.model.ModelManager; import planmysem.model.semester.Day; import planmysem.model.semester.ReadOnlyDay; import planmysem.model.slot.ReadOnlySlot; import planmysem.model.slot.Slot; import planmysem.testutil.SlotBuilder; -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.util.*; - -import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertFalse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static planmysem.common.Messages.MESSAGE_INVALID_MULTIPLE_PARAMS; -import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS; -import static planmysem.logic.commands.ListCommand.MESSAGE_SUCCESS_NONE; - public class ListCommandTest { private Model model; private Model expectedModel; diff --git a/test/java/planmysem/logic/LogicManagerTest.java b/test/java/planmysem/logic/LogicManagerTest.java index b8bef84ef..f360bcf21 100644 --- a/test/java/planmysem/logic/LogicManagerTest.java +++ b/test/java/planmysem/logic/LogicManagerTest.java @@ -1,10 +1,19 @@ package planmysem.logic; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static planmysem.common.Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX; -import java.io.IOException; +import java.io.File; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.util.Pair; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -18,11 +27,15 @@ import planmysem.logic.parser.exceptions.ParseException; import planmysem.model.Model; import planmysem.model.ModelManager; +import planmysem.model.semester.Day; +import planmysem.model.semester.ReadOnlyDay; +import planmysem.model.slot.ReadOnlySlot; +import planmysem.model.slot.Slot; import planmysem.storage.StorageFile; +import planmysem.testutil.SlotBuilder; public class LogicManagerTest { - private static final IOException DUMMY_IO_EXCEPTION = new IOException("dummy exception"); private static final String testFileName = "testSaveFile.txt"; @Rule @@ -43,6 +56,73 @@ public void setUp() throws Exception { model = new ModelManager(); } + + @Test + public void execute_throwsStorageOperationException() throws CommandException, ParseException { + // delete save file + File file = new File(temporaryFolder.getRoot().getPath() + "\\" + testFileName); + file.setReadOnly(); + + Slot slot = new SlotBuilder().slotOne(); + String cmd = SlotBuilder.generateAddCommand(slot, 2, ""); + + thrown.expect(CommandException.class); + logic.execute(cmd); + } + + @Test + public void getStorageFilePath() { + assertEquals(logic.getStorageFilePath(), storageFile.getPath()); + } + + @Test + public void getLastShownSlots() throws CommandException, ParseException { + Slot slot = new SlotBuilder().slotOne(); + String cmd = SlotBuilder.generateAddCommand(slot, 2, ""); + logic.execute(cmd); + logic.execute("list n/CS2113T Tutorial"); + + List>> lastShownSlots + = new ArrayList<>(); + Day day = new Day(DayOfWeek.TUESDAY, "Week 1"); + day.addSlot(slot); + lastShownSlots.add(new Pair<>(LocalDate.of(2019, 1, 15), + new Pair<>(day, new SlotBuilder().slotOne()))); + + assertEquals(logic.getLastShownSlots(), lastShownSlots); + } + + @Test + public void getHistory() throws Exception { + ObservableList expectedHistory = + FXCollections.observableArrayList(); + + Slot slot = new SlotBuilder().slotOne(); + String cmd = SlotBuilder.generateAddCommand(slot, 2, ""); + logic.execute(cmd); + expectedHistory.add(cmd); + + logic.execute("list n/CS2113T Tutorial"); + expectedHistory.add("list n/CS2113T Tutorial"); + + logic.execute("view week"); + expectedHistory.add("view week"); + + logic.execute("d 1"); + expectedHistory.add("d 1"); + + assertEquals(logic.getHistory(), expectedHistory); + assertEquals(logic.getHistory().hashCode(), expectedHistory.hashCode()); + + // equal same object + assertEquals(logic.getHistory(), logic.getHistory()); + assertEquals(logic.getHistory().hashCode(), logic.getHistory().hashCode()); + + // equal null + assertNotEquals(logic.getHistory(), null); + } + + @Test public void execute_commandExecutionError_throwsCommandException() { String deleteCommand = "delete 3"; @@ -56,33 +136,6 @@ public void execute_validCommand_success() { assertCommandSuccess(listCommand, ListCommand.MESSAGE_SUCCESS_NONE, model); assertHistoryCorrect(listCommand); } -// -// @Test -// public void execute_storageThrowsIoException_throwsCommandException() throws Exception { -// // Setup LogicManager with JsonAddressBookIoExceptionThrowingStub -// JsonAddressBookStorage addressBookStorage = -// new JsonAddressBookIoExceptionThrowingStub(temporaryFolder.newFile().toPath()); -// JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.newFile().toPath()); -// StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage); -// logic = new LogicManager(model, storage); -// -// // Execute add command -// String addCommand = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY -// + ADDRESS_DESC_AMY; -// Person expectedPerson = new PersonBuilder(AMY).withTags().build(); -// ModelManager expectedModel = new ModelManager(); -// expectedModel.addPerson(expectedPerson); -// expectedModel.commitAddressBook(); -// String expectedMessage = LogicManager.FILE_OPS_ERROR_MESSAGE + DUMMY_IO_EXCEPTION; -// assertCommandBehavior(CommandException.class, addCommand, expectedMessage, expectedModel); -// assertHistoryCorrect(addCommand); -// } -// -// @Test -// public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() { -// thrown.expect(UnsupportedOperationException.class); -// logic.getFilteredPersonList().remove(0); -// } /** * Executes the command, confirms that no exceptions are thrown and that the result message is correct. @@ -129,7 +182,7 @@ private void assertCommandBehavior(Class expectedException, String inputComma try { CommandResult result = logic.execute(inputCommand); - assertEquals(expectedException, null); + assertNull(expectedException); assertEquals(expectedMessage, result.getFeedbackToUser()); } catch (CommandException | ParseException e) { assertEquals(expectedException, e.getClass()); diff --git a/test/java/planmysem/logic/parser/AddCommandParserTest.java b/test/java/planmysem/logic/parser/AddCommandParserTest.java index c0879af69..8eb5be62f 100644 --- a/test/java/planmysem/logic/parser/AddCommandParserTest.java +++ b/test/java/planmysem/logic/parser/AddCommandParserTest.java @@ -15,6 +15,7 @@ import org.junit.Before; import org.junit.Test; + import planmysem.common.Clock; import planmysem.logic.commands.AddCommand; import planmysem.model.recurrence.Recurrence; @@ -25,7 +26,7 @@ public class AddCommandParserTest { @Before public void setup() { - Clock.set("2019-01-13T10:00:00Z"); + Clock.set("2019-01-14T10:00:00Z"); } @Test @@ -55,8 +56,7 @@ public void parse_minimalFields_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), null - ) - , new Recurrence( + ), new Recurrence( null, LocalDate.of(2019, 1, 14) ))); @@ -73,8 +73,7 @@ public void parse_optionalFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) - ) - , new Recurrence( + ), new Recurrence( null, 1 ))); @@ -88,14 +87,14 @@ public void parse_optionalFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>() - ) - , new Recurrence( + ), new Recurrence( null, 1 ))); assertParseSuccess(parser, - "n/CS2113T Tutorial l/COM2 04-01 d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial", + "n/CS2113T Tutorial l/COM2 04-01 d/mon st/08:00 et/09:00 " + + "des/Topic: Sequence Diagram t/CS2113T t/Tutorial", new AddCommand(new Slot( "CS2113T Tutorial", "COM2 04-01", @@ -103,8 +102,7 @@ public void parse_optionalFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) - ) - , new Recurrence( + ), new Recurrence( null, 1 ))); @@ -118,8 +116,7 @@ public void parse_optionalFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>() - ) - , new Recurrence( + ), new Recurrence( null, 1 ))); @@ -133,8 +130,7 @@ public void parse_optionalFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) - ) - , new Recurrence( + ), new Recurrence( null, 1 ))); @@ -148,15 +144,14 @@ public void parse_optionalFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>() - ) - , new Recurrence( + ), new Recurrence( null, 1 ))); } @Test - public void parse_AllFieldsMissing_success() { + public void parse_allFieldsMissing_success() { assertParseSuccess(parser, "n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", new AddCommand(new Slot( @@ -181,14 +176,14 @@ public void parse_AllFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>() - ) - , new Recurrence( + ), new Recurrence( new HashSet<>(Arrays.asList("exam")), 1 ))); assertParseSuccess(parser, - "n/CS2113T Tutorial r/reading r/exam l/COM2 04-01 d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial", + "n/CS2113T Tutorial r/reading r/exam l/COM2 04-01 " + + "d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial", new AddCommand(new Slot( "CS2113T Tutorial", "COM2 04-01", @@ -196,8 +191,7 @@ public void parse_AllFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) - ) - , new Recurrence( + ), new Recurrence( new HashSet<>(Arrays.asList("reading", "exam")), 1 ))); @@ -211,8 +205,7 @@ public void parse_AllFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>() - ) - , new Recurrence( + ), new Recurrence( new HashSet<>(Arrays.asList("normal", "exam")), 1 ))); @@ -226,8 +219,7 @@ public void parse_AllFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) - ) - , new Recurrence( + ), new Recurrence( new HashSet<>(Arrays.asList("reading", "recess")), 1 ))); @@ -241,8 +233,7 @@ public void parse_AllFieldsMissing_success() { LocalTime.of(8, 0), LocalTime.of(9, 0), new HashSet<>() - ) - , new Recurrence( + ), new Recurrence( new HashSet<>(Arrays.asList("reading", "recess", "normal", "exam")), 1 ))); @@ -282,13 +273,15 @@ public void parse_compulsoryFieldMissing_failure() { public void parse_invalidDate_failure() { // invalid day assertParseFailure(parser, - "add n/CS2113T Tutorial d/0 st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", + "add n/CS2113T Tutorial d/0 st/08:00 et/09:00 " + + "des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, AddCommand.MESSAGE_USAGE, MESSAGE_INVALID_DATE)); // invalid date assertParseFailure(parser, - "add n/CS2113T Tutorial d/19999 st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", + "add n/CS2113T Tutorial d/19999 st/08:00 et/09:00 " + + "des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, AddCommand.MESSAGE_USAGE, MESSAGE_INVALID_DATE)); } @@ -297,17 +290,20 @@ public void parse_invalidDate_failure() { public void parse_invalidTime_failure() { // invalid start time assertParseFailure(parser, - "add n/CS2113T Tutorial d/mon st/25:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", + "add n/CS2113T Tutorial d/mon st/25:00 et/09:00 " + + "des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, AddCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME)); // invalid end time assertParseFailure(parser, - "add n/CS2113T Tutorial d/mon st/08:00 et/25:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", + "add n/CS2113T Tutorial d/mon st/08:00 et/25:00 " + + "des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, AddCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME)); assertParseFailure(parser, - "add n/CS2113T Tutorial d/mon st/08:00 et/13:00AM des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", + "add n/CS2113T Tutorial d/mon st/08:00 et/13:00AM " + + "des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal", String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, AddCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME)); } diff --git a/test/java/planmysem/logic/parser/CommandParserTestUtil.java b/test/java/planmysem/logic/parser/CommandParserTestUtil.java index c319f89b2..4b8fc0cfc 100644 --- a/test/java/planmysem/logic/parser/CommandParserTestUtil.java +++ b/test/java/planmysem/logic/parser/CommandParserTestUtil.java @@ -8,13 +8,13 @@ /** * Contains helper methods for testing command parsers. */ -public class CommandParserTestUtil { +class CommandParserTestUtil { /** * Asserts that the parsing of {@code userInput} by {@code parser} is successful and the command created * equals to {@code expectedCommand}. */ - public static void assertParseSuccess(Parser parser, String userInput, Command expectedCommand) { + static void assertParseSuccess(Parser parser, String userInput, Command expectedCommand) { try { Command command = parser.parse(userInput); assertEquals(expectedCommand, command); @@ -27,7 +27,7 @@ public static void assertParseSuccess(Parser parser, String userInput, Command e * Asserts that the parsing of {@code userInput} by {@code parser} is unsuccessful and the error message * equals to {@code expectedMessage}. */ - public static void assertParseFailure(Parser parser, String userInput, String expectedMessage) { + static void assertParseFailure(Parser parser, String userInput, String expectedMessage) { try { parser.parse(userInput); throw new AssertionError("The expected ParseException was not thrown."); diff --git a/test/java/planmysem/logic/parser/DeleteCommandParserTest.java b/test/java/planmysem/logic/parser/DeleteCommandParserTest.java index 3b179a29e..e62fd1d11 100644 --- a/test/java/planmysem/logic/parser/DeleteCommandParserTest.java +++ b/test/java/planmysem/logic/parser/DeleteCommandParserTest.java @@ -5,10 +5,12 @@ import static planmysem.logic.parser.CommandParserTestUtil.assertParseSuccess; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import org.junit.Before; import org.junit.Test; + import planmysem.common.Clock; import planmysem.logic.commands.DeleteCommand; @@ -26,7 +28,7 @@ public void parse_validTags_success() { assertParseSuccess(parser, "t/CS2113T", new DeleteCommand( - new HashSet<>(Arrays.asList("CS2113T") + new HashSet<>(Collections.singletonList("CS2113T") ) ) ); diff --git a/test/java/planmysem/logic/parser/EditCommandParserTest.java b/test/java/planmysem/logic/parser/EditCommandParserTest.java index f1a91b9d4..5160c77e7 100644 --- a/test/java/planmysem/logic/parser/EditCommandParserTest.java +++ b/test/java/planmysem/logic/parser/EditCommandParserTest.java @@ -1,15 +1,20 @@ package planmysem.logic.parser; import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL; +import static planmysem.common.Messages.MESSAGE_INVALID_TIME; +import static planmysem.common.Messages.MESSAGE_NOTHING_TO_EDIT; import static planmysem.logic.parser.CommandParserTestUtil.assertParseFailure; import static planmysem.logic.parser.CommandParserTestUtil.assertParseSuccess; import java.time.LocalTime; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import org.junit.Before; import org.junit.Test; + import planmysem.common.Clock; import planmysem.logic.commands.EditCommand; @@ -32,7 +37,7 @@ public void parse_validTags_success() { -1, "COM2 04-01", null, - new HashSet<>(Arrays.asList("CS2113T")), + new HashSet<>(Collections.singletonList("CS2113T")), new HashSet<>() ) ); @@ -42,7 +47,7 @@ public void parse_validTags_success() { "t/CS2113T t/Tutorial nst/08:00 net/09:00 t/Hard", new EditCommand( null, - LocalTime.of(8,0), + LocalTime.of(8, 0), 60, null, null, @@ -61,7 +66,7 @@ public void parse_validTags_success() { "COM2 04-01", "So tough", new HashSet<>(Arrays.asList("CS2113T", "Tutorial", "Hard")), - new HashSet<>(Arrays.asList("new tag")) + new HashSet<>(Collections.singletonList("new tag")) ) ); } @@ -128,8 +133,9 @@ public void parse_noIndexNoTag_failure() { } @Test - public void parse_InvalidStartTime_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE); + public void parse_invalidStartTime_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, + EditCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME); assertParseFailure(parser, "1 nst/25:00", @@ -138,12 +144,35 @@ public void parse_InvalidStartTime_failure() { } @Test - public void parse_InvalidEndTime_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE); + public void parse_invalidEndTime_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, + EditCommand.MESSAGE_USAGE, MESSAGE_INVALID_TIME); assertParseFailure(parser, "1 net/25:00", expectedMessage ); } + + + @Test + public void parse_nothingToEdit_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT_ADDITIONAL, + EditCommand.MESSAGE_USAGE, MESSAGE_NOTHING_TO_EDIT); + + assertParseFailure(parser, + "1 nnt/", + expectedMessage + ); + + assertParseFailure(parser, + "1 nl/", + expectedMessage + ); + + assertParseFailure(parser, + "t/test ndes/", + expectedMessage + ); + } } diff --git a/test/java/planmysem/logic/parser/ParserManagerTest.java b/test/java/planmysem/logic/parser/ParserManagerTest.java index 7d3717933..057b2b3ca 100644 --- a/test/java/planmysem/logic/parser/ParserManagerTest.java +++ b/test/java/planmysem/logic/parser/ParserManagerTest.java @@ -6,6 +6,7 @@ import java.time.LocalDate; import java.time.LocalTime; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import org.junit.Rule; @@ -31,7 +32,7 @@ public class ParserManagerTest { private final ParserManager parser = new ParserManager(); @Test - public void parseCommand_add_via_day() throws Exception { + public void parse_commandAddViaDay() throws Exception { AddCommand command = (AddCommand) parser.parseCommand( AddCommand.COMMAND_WORD + " " + "n/CS2113T Tutorial d/mon st/08:00 et/09:00"); assertEquals(new AddCommand(new Slot( @@ -41,8 +42,7 @@ public void parseCommand_add_via_day() throws Exception { LocalTime.of(8, 0), LocalTime.of(9, 0), null - ) - , new Recurrence( + ), new Recurrence( null, 1 )), command); @@ -56,17 +56,17 @@ public void parseCommand_add_via_day() throws Exception { LocalTime.of(8, 0), LocalTime.of(9, 0), null - ) - , new Recurrence( + ), new Recurrence( null, 1 )), commandShort); } @Test - public void parseCommand_add_via_date() throws Exception { + public void parse_commandAddViaDate() throws Exception { AddCommand command = (AddCommand) parser.parseCommand( - AddCommand.COMMAND_WORD + " " + "n/CS2113T Tutorial d/21-01-2019 st/08:00 et/09:00"); + AddCommand.COMMAND_WORD + " " + + "n/CS2113T Tutorial d/21-01-2019 st/08:00 et/09:00"); assertEquals(new AddCommand(new Slot( "CS2113T Tutorial", null, @@ -74,15 +74,14 @@ public void parseCommand_add_via_date() throws Exception { LocalTime.of(8, 0), LocalTime.of(9, 0), null - ) - , new Recurrence( + ), new Recurrence( null, LocalDate.of(2019, 1, 21) )), command); } @Test - public void parseCommand_delete_via_index() throws Exception { + public void parse_commandDeleteViaIndex() throws Exception { DeleteCommand command = (DeleteCommand) parser.parseCommand( DeleteCommand.COMMAND_WORD + " 1"); assertEquals(new DeleteCommand(1), command); @@ -99,14 +98,14 @@ public void parseCommand_delete_via_index() throws Exception { } @Test - public void parseCommand_delete_via_tags() throws Exception { + public void parse_commandDeleteViaTags() throws Exception { DeleteCommand command = (DeleteCommand) parser.parseCommand( DeleteCommand.COMMAND_WORD + " t/CS2113T t/Tutorial"); assertEquals(new DeleteCommand(new HashSet<>(Arrays.asList("CS2113T", "Tutorial"))), command); } @Test - public void parseCommand_edit_via_index() throws Exception { + public void parse_commandEditViaIndex() throws Exception { EditCommand command = (EditCommand) parser.parseCommand( EditCommand.COMMAND_WORD + " " + "1 nl/COM2 04-01"); assertEquals(new EditCommand( @@ -135,7 +134,7 @@ public void parseCommand_edit_via_index() throws Exception { } @Test - public void parseCommand_edit_via_tags() throws Exception { + public void parse_commandEditViaTags() throws Exception { EditCommand command = (EditCommand) parser.parseCommand( EditCommand.COMMAND_WORD + " " + "t/CS2113T nl/COM2 04-01"); assertEquals(new EditCommand( @@ -144,7 +143,7 @@ public void parseCommand_edit_via_tags() throws Exception { -1, "COM2 04-01", null, - new HashSet<>(Arrays.asList("CS2113T")), + new HashSet<>(Collections.singletonList("CS2113T")), new HashSet<>() ), command); } @@ -189,7 +188,6 @@ public void parseCommand_view() throws Exception { assertEquals(new ViewCommand(new String[]{"month"}), commandShort); } -// // @Test // public void parseCommand_find() throws Exception { // List keywords = Arrays.asList("foo", "bar", "baz"); @@ -197,58 +195,58 @@ public void parseCommand_view() throws Exception { // FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" "))); // assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command); // } -// -// -// @Test -// public void parseCommand_history() throws Exception { -// assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD) instanceof HistoryCommand); -// assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD + " 3") instanceof HistoryCommand); -// -// try { -// parser.parseCommand("histories"); -// throw new AssertionError("The expected ParseException was not thrown."); -// } catch (ParseException pe) { -// assertEquals(MESSAGE_UNKNOWN_COMMAND, pe.getMessage()); -// } -// } -// -// @Test -// public void parseCommand_list() throws Exception { -// assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand); -// assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand); -// } -// -// @Test -// public void parseCommand_select() throws Exception { -// SelectCommand command = (SelectCommand) parser.parseCommand( -// SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); -// assertEquals(new SelectCommand(INDEX_FIRST_PERSON), command); -// } -// -// @Test -// public void parseCommand_redoCommandWord_returnsRedoCommand() throws Exception { -// assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD) instanceof RedoCommand); -// assertTrue(parser.parseCommand("redo 1") instanceof RedoCommand); -// } -// -// @Test -// public void parseCommand_undoCommandWord_returnsUndoCommand() throws Exception { -// assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD) instanceof UndoCommand); -// assertTrue(parser.parseCommand("undo 3") instanceof UndoCommand); -// } -// -// @Test -// public void parseCommand_unrecognisedInput_throwsParseException() throws Exception { -// thrown.expect(ParseException.class); -// thrown.expectMessage(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); -// parser.parseCommand(""); -// } -// -// @Test -// public void parseCommand_unknownCommand_throwsParseException() throws Exception { -// thrown.expect(ParseException.class); -// thrown.expectMessage(MESSAGE_UNKNOWN_COMMAND); -// parser.parseCommand("unknownCommand"); -// } + + // + // @Test + // public void parseCommand_history() throws Exception { + // assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD) instanceof HistoryCommand); + // assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD + " 3") instanceof HistoryCommand); + // + // try { + // parser.parseCommand("histories"); + // throw new AssertionError("The expected ParseException was not thrown."); + // } catch (ParseException pe) { + // assertEquals(MESSAGE_UNKNOWN_COMMAND, pe.getMessage()); + // } + // } + // + // @Test + // public void parseCommand_list() throws Exception { + // assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand); + // assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand); + // } + // + // @Test + // public void parseCommand_select() throws Exception { + // SelectCommand command = (SelectCommand) parser.parseCommand( + // SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); + // assertEquals(new SelectCommand(INDEX_FIRST_PERSON), command); + // } + // + // @Test + // public void parseCommand_redoCommandWord_returnsRedoCommand() throws Exception { + // assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD) instanceof RedoCommand); + // assertTrue(parser.parseCommand("redo 1") instanceof RedoCommand); + // } + // + // @Test + // public void parseCommand_undoCommandWord_returnsUndoCommand() throws Exception { + // assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD) instanceof UndoCommand); + // assertTrue(parser.parseCommand("undo 3") instanceof UndoCommand); + // } + // + // @Test + // public void parseCommand_unrecognisedInput_throwsParseException() throws Exception { + // thrown.expect(ParseException.class); + // thrown.expectMessage(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); + // parser.parseCommand(""); + // } + // + // @Test + // public void parseCommand_unknownCommand_throwsParseException() throws Exception { + // thrown.expect(ParseException.class); + // thrown.expectMessage(MESSAGE_UNKNOWN_COMMAND); + // parser.parseCommand("unknownCommand"); + // } } diff --git a/test/java/planmysem/model/ModelManagerTest.java b/test/java/planmysem/model/ModelManagerTest.java new file mode 100644 index 000000000..28188f0a8 --- /dev/null +++ b/test/java/planmysem/model/ModelManagerTest.java @@ -0,0 +1,106 @@ +package planmysem.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javafx.util.Pair; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import planmysem.common.Clock; +import planmysem.model.semester.Day; +import planmysem.model.semester.ReadOnlyDay; +import planmysem.model.semester.Semester; +import planmysem.model.slot.ReadOnlySlot; +import planmysem.model.slot.Slot; +import planmysem.testutil.SlotBuilder; + +public class ModelManagerTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setup() { + Clock.set("2019-01-14T10:00:00Z"); + } + + @Test + public void clearLastShownList() { + ModelManager modelManager = new ModelManager(); + List>> lastShownSlots = new ArrayList<>(); + Day day = new Day(DayOfWeek.TUESDAY, "Week 1"); + lastShownSlots.add(new Pair<>(LocalDate.of(2019, 1, 15), + new Pair<>(day, new SlotBuilder().slotOne()))); + + modelManager.setLastShownList(lastShownSlots); + assertEquals(modelManager.lastShownList, lastShownSlots); + + modelManager.clearLastShownList(); + assertEquals(modelManager.lastShownList, Collections.EMPTY_LIST); + } + + @Test + public void undo() throws Semester.DateNotFoundException { + ModelManager modelManager = new ModelManager(); + Slot slot = new SlotBuilder().slotOne(); + LocalDate date = LocalDate.of(2019, 1, 15); + modelManager.addSlot(date, slot); + modelManager.commit(); + + // test canUndo() + assertTrue(modelManager.canUndo()); + + modelManager.undo(); + + ModelManager expectedModelManager = new ModelManager(); + + assertEquals(modelManager.getPlanner().getSemester(), + expectedModelManager.getPlanner().getSemester()); + } + + @Test + public void redo() throws Semester.DateNotFoundException { + ModelManager modelManager = new ModelManager(); + Slot slot = new SlotBuilder().slotOne(); + LocalDate date = LocalDate.of(2019, 1, 15); + modelManager.addSlot(date, slot); + modelManager.commit(); + modelManager.undo(); + + // test canRedo() + assertTrue(modelManager.canRedo()); + + modelManager.redo(); + + ModelManager expectedModelManager = new ModelManager(); + expectedModelManager.addSlot(date, slot); + + assertEquals(modelManager.getPlanner().getSemester(), + expectedModelManager.getPlanner().getSemester()); + } + + @Test + public void equals() { + ModelManager modelManager = new ModelManager(); + ModelManager expectedModelManager = new ModelManager(); + + // equals same object + assertEquals(modelManager, modelManager); + assertEquals(modelManager.hashCode(), modelManager.hashCode()); + + // equals null + assertNotEquals(modelManager, null); + + // different objects same values + assertEquals(modelManager, expectedModelManager); + assertEquals(modelManager.hashCode(), expectedModelManager.hashCode()); + } +} diff --git a/test/java/planmysem/model/PlannerTest.java b/test/java/planmysem/model/PlannerTest.java index fd09fb2ce..b464d6dc5 100644 --- a/test/java/planmysem/model/PlannerTest.java +++ b/test/java/planmysem/model/PlannerTest.java @@ -1,150 +1,30 @@ package planmysem.model; -import static junit.framework.TestCase.assertEquals; - -import java.time.LocalDate; -import java.time.temporal.WeekFields; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; +import static org.junit.Assert.assertEquals; +import org.junit.Before; import org.junit.Test; - import planmysem.common.Clock; -import planmysem.model.semester.Day; -import planmysem.model.semester.Semester; - public class PlannerTest { - @Test - public void execute_generateSemester() { - TestDataHelper helper = new TestDataHelper(); - Semester generatedSemester; - Semester expectedSemester; - - // Assert Semester One generation - generatedSemester = Semester.generateSemester(LocalDate.of(2018, 8, 6)); - LocalDate semOneDate = LocalDate.of(2018, 8, 6); - expectedSemester = helper.generateSemesterFromDate(semOneDate, "Sem 1"); - assertSameSemester(generatedSemester, expectedSemester); - - expectedSemester = Semester.generateSemester(LocalDate.of(2018, 10, 6)); - assertSameSemester(generatedSemester, expectedSemester); - - // Assert Semester Two generation - generatedSemester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); - LocalDate semTwoDate = LocalDate.of(2019, 1, 14); - expectedSemester = helper.generateSemesterFromDate(semTwoDate, "Sem 2"); - assertSameSemester(generatedSemester, expectedSemester); - - expectedSemester = Semester.generateSemester(LocalDate.of(2019, 3, 17)); - assertSameSemester(generatedSemester, expectedSemester); + @Before + public void setup() { + Clock.set("2019-01-14T10:00:00Z"); } - /** - * Asserts that the generated and expected Semester contents are equal. - */ - private void assertSameSemester(Semester generatedSemester, Semester expectedSemester) { - //Confirm the state of model is as expected - assertEquals(generatedSemester.hashCode(), expectedSemester.hashCode()); + @Test + public void initTest() { + Planner planner = new Planner(); + Planner expectedPlanner = new Planner(planner.getSemester()); + assertEquals(expectedPlanner, planner); } - /** - * A utility class to generate test model. - */ - public class TestDataHelper { - - /** - * Generates a Semester from the given date - * - * @param startDate given date which the semester should start from - * @param acadSem the semester of the academic year - * @return a Semester object from a specified date - */ - Semester generateSemesterFromDate(LocalDate startDate, String acadSem) { - String acadYear = null; - LocalDate endDate = LocalDate.now(Clock.get()); - int givenYear = startDate.getYear(); - int weekOfStartDate = startDate.get(WeekFields.ISO.weekOfWeekBasedYear()); - int noOfWeeks = 0; - HashMap weekNames = new HashMap<>(); - HashMap days = new HashMap<>(); - Set recessDays = new HashSet<>(); - Set readingDays = new HashSet<>(); - Set normalDays = new HashSet<>(); - Set examDays = new HashSet<>(); - - if ("Sem 1".equals(acadSem)) { - noOfWeeks = 18; - acadYear = "AY" + givenYear + "/" + (givenYear + 1); - endDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfStartDate + 18 - 1); - endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - - weekNames.put(weekOfStartDate, "Orientation Week"); - int week = 1; - for (int i = weekOfStartDate + 1; i < weekOfStartDate + 7; i++) { - weekNames.put(i, "Week " + week); - week++; - } - weekNames.put(weekOfStartDate + 7, "Recess Week"); - week = 7; - for (int i = weekOfStartDate + 8; i < weekOfStartDate + 15; i++) { - weekNames.put(i, "Week " + week); - week++; - } - weekNames.put(weekOfStartDate + 15, "Reading Week"); - weekNames.put(weekOfStartDate + 16, "Examination Week"); - weekNames.put(weekOfStartDate + 17, "Examination Week"); - } else if ("Sem 2".equals(acadSem)) { - noOfWeeks = 17; - acadYear = "AY" + (givenYear - 1) + "/" + givenYear; - endDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfStartDate + 17 - 1); - endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - - int week = 1; - for (int i = weekOfStartDate; i < weekOfStartDate + 6; i++) { - weekNames.put(i, "Week " + week); - week++; - } - weekNames.put(weekOfStartDate + 6, "Recess Week"); - week = 7; - for (int i = weekOfStartDate + 7; i < weekOfStartDate + 14; i++) { - weekNames.put(i, "Week " + week); - week++; - } - weekNames.put(weekOfStartDate + 14, "Reading Week"); - weekNames.put(weekOfStartDate + 15, "Examination Week"); - weekNames.put(weekOfStartDate + 16, "Examination Week"); - } - - // Initialises HashMap and Sets of all days in current semester - List datesList = startDate.datesUntil(endDate.plusDays(1)).collect(Collectors.toList()); - for (LocalDate date: datesList) { - int weekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); - String weekType = weekNames.get(weekOfYear); - days.put(date, new Day(date.getDayOfWeek(), weekType)); - switch (weekType) { - case "Recess Week": - recessDays.add(date); - break; - case "Reading Week": - readingDays.add(date); - break; - case "Examination Week": - examDays.add(date); - break; - default: - normalDays.add(date); - break; - } - } - - return new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, - recessDays, readingDays, normalDays, examDays); - } + @Test + public void equals() { + Planner planner = new Planner(); + Planner expectedPlanner = new Planner(planner); + assertEquals(expectedPlanner, planner); + assertEquals(expectedPlanner.hashCode(), planner.hashCode()); } - } diff --git a/test/java/planmysem/model/Recurrence/RecurrenceTest.java b/test/java/planmysem/model/Recurrence/RecurrenceTest.java new file mode 100644 index 000000000..3f9c33fb2 --- /dev/null +++ b/test/java/planmysem/model/Recurrence/RecurrenceTest.java @@ -0,0 +1,95 @@ +package planmysem.model.Recurrence; + +import static org.junit.Assert.assertEquals; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.HashSet; + +import org.junit.Before; +import org.junit.Test; + +import planmysem.common.Clock; +import planmysem.model.recurrence.Recurrence; +import planmysem.model.semester.Semester; + + +public class RecurrenceTest { + + private Semester semester; + + @Before + public void setup() { + Clock.set("2019-01-14T10:00:00Z"); + semester = Semester.generateSemester(LocalDate.now(Clock.get())); + } + + @Test + public void generateDatesTest() { + Recurrence all = new Recurrence(new HashSet<>( + Arrays.asList( + "normal", + "recess", + "reading", + "exam", + "past" + )), 1); + assertEquals(all.generateDates(semester).size(), 17); + + Clock.set("2019-05-12T10:00:00Z"); + Recurrence noPast = new Recurrence(new HashSet<>( + Arrays.asList( + "normal", + "recess", + "reading", + "exam" + )), 2); + assertEquals(noPast.generateDates(semester).size(), 0); + + Clock.set("2019-01-14T10:00:00Z"); + Recurrence futureOnly = new Recurrence(new HashSet<>( + Arrays.asList( + "normal", + "recess", + "reading", + "exam" + )), 2); + assertEquals(futureOnly.generateDates(semester).size(), 17); + } + + @Test + public void getDateTest() { + Recurrence all = new Recurrence(new HashSet<>( + Arrays.asList( + "normal", + "recess", + "reading", + "exam", + "past" + )), 1); + assertEquals(all.getDate(), LocalDate.of(2019, 1, 21)); + } + + @Test + public void equals() { + Recurrence all = new Recurrence(new HashSet<>( + Arrays.asList( + "normal", + "recess", + "reading", + "exam", + "past" + )), 1); + + Recurrence allCopy = new Recurrence(new HashSet<>( + Arrays.asList( + "normal", + "recess", + "reading", + "exam", + "past" + )), 1); + assertEquals(all, allCopy); + assertEquals(all.hashCode(), allCopy.hashCode()); + } +} diff --git a/test/java/planmysem/model/Semester/DayTest.java b/test/java/planmysem/model/Semester/DayTest.java new file mode 100644 index 000000000..c1df560f8 --- /dev/null +++ b/test/java/planmysem/model/Semester/DayTest.java @@ -0,0 +1,99 @@ +package planmysem.model.Semester; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.time.DayOfWeek; +import java.util.ArrayList; +import java.util.Collections; + +import org.junit.Test; + +import planmysem.model.semester.Day; +import planmysem.model.slot.Slot; +import planmysem.testutil.SlotBuilder; + + +public class DayTest { + + @Test + public void initTest() { + Slot slot = new SlotBuilder().slotOne(); + Day day = new Day(DayOfWeek.of(1), + "Week 1", + Collections.singletonList(slot)); + + assertEquals(day.getSlots(), Collections.singletonList(slot)); + } + + @Test + public void containsTest() { + Day day = new Day(DayOfWeek.of(1), "Week 1"); + Slot slot = new SlotBuilder().slotOne(); + + assertFalse(day.contains(slot)); + + day.addSlot(slot); + assertTrue(day.contains(slot)); + } + + @Test + public void getDayOfWeekTest() { + Day day = new Day(DayOfWeek.of(1), "Week 1"); + + assertEquals(day.getDayOfWeek(), DayOfWeek.of(1)); + assertNotEquals(day.getDayOfWeek(), DayOfWeek.of(2)); + } + + @Test + public void getDayTest() { + DayOfWeek dayOfWeek = DayOfWeek.of(1); + Day day = new Day(dayOfWeek, "Week 1"); + + assertEquals(day.getDay(), dayOfWeek.toString()); + + DayOfWeek dayOfWeek2 = DayOfWeek.of(2); + assertNotEquals(day.getDay(), dayOfWeek2.toString()); + } + + @Test + public void getTypeTest() { + Day day = new Day(DayOfWeek.of(1), "Week 1"); + + assertEquals(day.getType(), "Week 1"); + assertNotEquals(day.getType(), "Week 2"); + } + + @Test + public void getSlotsTest() { + Day day = new Day(DayOfWeek.of(1), "Week 1"); + + assertEquals(day.getSlots(), new ArrayList<>()); + + Slot slot = new SlotBuilder().slotOne(); + day.addSlot(slot); + assertEquals(day.getSlots(), Collections.singletonList(slot)); + } + + @Test + public void equalsTest() { + assertEquals(new Day(DayOfWeek.of(1), "Week 1"), + new Day(DayOfWeek.of(1), "Week 1")); + assertEquals(new Day(DayOfWeek.of(1), "Week 2"), + new Day(DayOfWeek.of(1), "Week 2")); + assertEquals(new Day(DayOfWeek.of(2), "Week 2"), + new Day(DayOfWeek.of(2), "Week 2")); + + assertNotEquals(new Day(DayOfWeek.of(2), "Week 2"), + new Day(DayOfWeek.of(3), "Week 2")); + assertNotEquals(new Day(DayOfWeek.of(2), "Week 2"), + new Day(DayOfWeek.of(2), "Week 3")); + + // test hashcode + assertEquals(new Day(DayOfWeek.of(1), "Week 1").hashCode(), + new Day(DayOfWeek.of(1), "Week 1").hashCode()); + + } +} diff --git a/test/java/planmysem/model/Semester/SemesterTest.java b/test/java/planmysem/model/Semester/SemesterTest.java new file mode 100644 index 000000000..75ba905f0 --- /dev/null +++ b/test/java/planmysem/model/Semester/SemesterTest.java @@ -0,0 +1,255 @@ +package planmysem.model.Semester; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.temporal.WeekFields; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import planmysem.common.Clock; +import planmysem.model.semester.Day; +import planmysem.model.semester.Semester; +import planmysem.model.slot.Slot; +import planmysem.testutil.SlotBuilder; + + +public class SemesterTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void initTest() { + // sem 1 + Semester generatedSemester = Semester.generateSemester(LocalDate.of(2018, 8, 14)); + Semester expectedSemester = new Semester(generatedSemester); + assertEquals(generatedSemester, expectedSemester); + + // vacation + generatedSemester = Semester.generateSemester(LocalDate.of(2018, 12, 10)); + expectedSemester = new Semester(generatedSemester); + assertEquals(generatedSemester, expectedSemester); + + // sem 2 + generatedSemester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + expectedSemester = new Semester(generatedSemester); + assertEquals(generatedSemester, expectedSemester); + + // vacation + generatedSemester = Semester.generateSemester(LocalDate.of(2019, 6, 13)); + expectedSemester = new Semester(generatedSemester); + assertEquals(generatedSemester, expectedSemester); + } + + @Test + public void getSlotsTest() throws Exception { + Semester semester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + assertEquals(semester.getSlots(new HashSet<>(Arrays.asList("CS2113T", "Tutorial"))).size(), + 0); + semester.addSlot(LocalDate.of(2019, 1, 14), + new SlotBuilder().slotOne()); + assertEquals(semester.getSlots(new HashSet<>(Arrays.asList("CS2113T", "Tutorial"))).size(), + 1); + semester.addSlot(LocalDate.of(2019, 1, 15), + new SlotBuilder().slotOne()); + assertEquals(semester.getSlots(new HashSet<>(Arrays.asList("CS2113T", "Tutorial"))).size(), + 2); + } + + @Test + public void addSlotTest() throws Exception { + Semester semester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + Slot slot = new SlotBuilder().slotOne(); + Day day = semester.addSlot(LocalDate.of(2019, 1, 14), slot); + + Day expectedDay = new Day(DayOfWeek.MONDAY, "Week 1"); + expectedDay.addSlot(slot); + assertEquals(day, expectedDay); + } + + + @Test + public void addSlotTest_throwsDateNotFoundException() throws Exception { + Semester semester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + Slot slot = new SlotBuilder().slotOne(); + + // null date + thrown.expect(Semester.DateNotFoundException.class); + semester.addSlot(null, slot); + + // add before start date + thrown.expect(Semester.DateNotFoundException.class); + semester.addSlot(LocalDate.of(2019, 1, 12), slot); + + // add after end date + thrown.expect(Semester.DateNotFoundException.class); + semester.addSlot(LocalDate.of(2020, 1, 12), slot); + } + + @Test + public void execute_generateSemester() { + TestDataHelper helper = new TestDataHelper(); + + // Assert Semester One generation + Semester generatedSemester = Semester.generateSemester(LocalDate.of(2018, 8, 6)); + Semester expectedSemester = helper.generateSemesterFromDate(LocalDate.of(2018, 8, 6), "Sem 1"); + assertEquals(generatedSemester, expectedSemester); + + expectedSemester = Semester.generateSemester(LocalDate.of(2018, 10, 6)); + assertEquals(generatedSemester, expectedSemester); + + // Assert Semester Two generation + generatedSemester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + LocalDate semTwoDate = LocalDate.of(2019, 1, 14); + expectedSemester = helper.generateSemesterFromDate(semTwoDate, "Sem 2"); + assertEquals(generatedSemester, expectedSemester); + + expectedSemester = Semester.generateSemester(LocalDate.of(2019, 3, 17)); + assertEquals(generatedSemester, expectedSemester); + } + + @Test + public void containsSlotTest() throws Exception { + Semester semester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + Slot slot = new SlotBuilder().slotOne(); + semester.addSlot(LocalDate.of(2019, 1, 14), + slot); + assertTrue(semester.contains(LocalDate.of(2019, 1, 14), slot)); + } + + @Test + public void containsDayTest() { + Semester semester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + Day day = new Day(DayOfWeek.MONDAY, "Week 1"); + assertTrue(semester.contains(day)); + assertTrue(semester.contains(LocalDate.of(2019, 1, 14))); + assertFalse(semester.contains(LocalDate.of(2019, 1, 13))); + } + + @Test + public void getAcadCal() { + Semester semester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + Semester anotherSemester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); + assertEquals(semester.getAcadCal(), anotherSemester.getAcadCal()); + } + + @Test + public void equalsTest() { + assertEquals(Semester.generateSemester(LocalDate.now(Clock.get())), + Semester.generateSemester(LocalDate.now(Clock.get()))); + assertNotEquals(Semester.generateSemester(LocalDate.now(Clock.get())), + Semester.generateSemester(LocalDate.of(1999, 1, 1))); + + // test hashcode + assertEquals(Semester.generateSemester(LocalDate.now(Clock.get())).hashCode(), + Semester.generateSemester(LocalDate.now(Clock.get())).hashCode()); + assertNotEquals(Semester.generateSemester(LocalDate.now(Clock.get())).hashCode(), + Semester.generateSemester(LocalDate.of(1999, 1, 1)).hashCode()); + } + + /** + * A utility class to generate test model. + */ + public class TestDataHelper { + + /** + * Generates a Semester from the given date + * + * @param startDate given date which the semester should start from + * @param acadSem the semester of the academic year + * @return a Semester object from a specified date + */ + Semester generateSemesterFromDate(LocalDate startDate, String acadSem) { + String acadYear = null; + LocalDate endDate = LocalDate.now(Clock.get()); + int givenYear = startDate.getYear(); + int weekOfStartDate = startDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + int noOfWeeks = 0; + HashMap weekNames = new HashMap<>(); + HashMap days = new HashMap<>(); + Set recessDays = new HashSet<>(); + Set readingDays = new HashSet<>(); + Set normalDays = new HashSet<>(); + Set examDays = new HashSet<>(); + + if ("Sem 1".equals(acadSem)) { + noOfWeeks = 18; + acadYear = "AY" + givenYear + "/" + (givenYear + 1); + endDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfStartDate + 18 - 1); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + + weekNames.put(weekOfStartDate, "Orientation Week"); + int week = 1; + for (int i = weekOfStartDate + 1; i < weekOfStartDate + 7; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 7, "Recess Week"); + week = 7; + for (int i = weekOfStartDate + 8; i < weekOfStartDate + 15; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 15, "Reading Week"); + weekNames.put(weekOfStartDate + 16, "Examination Week"); + weekNames.put(weekOfStartDate + 17, "Examination Week"); + } else if ("Sem 2".equals(acadSem)) { + noOfWeeks = 17; + acadYear = "AY" + (givenYear - 1) + "/" + givenYear; + endDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfStartDate + 17 - 1); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + + int week = 1; + for (int i = weekOfStartDate; i < weekOfStartDate + 6; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 6, "Recess Week"); + week = 7; + for (int i = weekOfStartDate + 7; i < weekOfStartDate + 14; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 14, "Reading Week"); + weekNames.put(weekOfStartDate + 15, "Examination Week"); + weekNames.put(weekOfStartDate + 16, "Examination Week"); + } + + // Initialises HashMap and Sets of all days in current semester + List datesList = startDate.datesUntil(endDate.plusDays(1)).collect(Collectors.toList()); + for (LocalDate date: datesList) { + int weekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); + String weekType = weekNames.get(weekOfYear); + days.put(date, new Day(date.getDayOfWeek(), weekType)); + switch (weekType) { + case "Recess Week": + recessDays.add(date); + break; + case "Reading Week": + readingDays.add(date); + break; + case "Examination Week": + examDays.add(date); + break; + default: + normalDays.add(date); + break; + } + } + + return new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, + recessDays, readingDays, normalDays, examDays); + } + } +} diff --git a/test/java/planmysem/model/Slot/SlotTest.java b/test/java/planmysem/model/Slot/SlotTest.java new file mode 100644 index 000000000..19f8959aa --- /dev/null +++ b/test/java/planmysem/model/Slot/SlotTest.java @@ -0,0 +1,134 @@ +package planmysem.model.Slot; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.time.LocalTime; +import java.util.Arrays; +import java.util.HashSet; + +import org.junit.Before; +import org.junit.Test; + +import planmysem.model.slot.Slot; +import planmysem.testutil.SlotBuilder; + + +public class SlotTest { + private Slot slot; + private Slot slotNull; + + @Before + public void setup() { + slot = new SlotBuilder().slotOne(); + slotNull = new SlotBuilder().slotNull(); + } + + @Test + public void getName() { + assertEquals(slot.getName(), slot.getName()); + assertNotEquals(slot.getName(), slotNull.getName()); + } + + @Test + public void getLocation() { + assertEquals(slot.getLocation(), slot.getLocation()); + assertNull(slotNull.getLocation()); + assertNotEquals(slot.getLocation(), slotNull.getLocation()); + } + + @Test + public void getDescription() { + assertEquals(slot.getDescription(), slot.getDescription()); + assertNull(slotNull.getDescription()); + assertNotEquals(slot.getDescription(), slotNull.getDescription()); + } + + @Test + public void getDuration() { + assertEquals(slot.getDuration(), slot.getDuration()); + assertEquals(slotNull.getDuration(), 0); + assertNotEquals(slot.getDuration(), 0); + } + + @Test + public void getStartTime() { + assertEquals(slot.getStartTime(), slot.getStartTime()); + assertNotEquals(slot.getStartTime(), slotNull.getStartTime()); + } + + @Test + public void getTags() { + assertEquals(slot.getTags(), slot.getTags()); + assertTrue(slotNull.getTags().isEmpty()); + assertNotEquals(slot.getTags(), slotNull.getTags()); + } + + @Test + public void setName() { + assertNotEquals(slot.getName(), "test"); + slot.setName("test"); + assertEquals(slot.getName(), "test"); + slot.setName(null); + assertEquals(slot.getName(), "test"); + + } + + @Test + public void setLocation() { + assertNotEquals(slot.getLocation(), "test"); + slot.setLocation("test"); + assertEquals(slot.getLocation(), "test"); + slot.setLocation(null); + assertEquals(slot.getLocation(), "test"); + + } + + @Test + public void setDescription() { + assertNotEquals(slot.getDescription(), "test"); + slot.setDescription("test"); + assertEquals(slot.getDescription(), "test"); + slot.setDescription(null); + assertEquals(slot.getDescription(), "test"); + } + + @Test + public void setStartTime() { + assertNotEquals(slot.getStartTime(), slotNull.getStartTime()); + slot.setStartTime(LocalTime.MIN); + assertEquals(slot.getStartTime(), LocalTime.MIN); + slot.setStartTime(null); + assertEquals(slot.getStartTime(), LocalTime.MIN); + } + + @Test + public void setTags() { + assertEquals(slot.getTags(), slot.getTags()); + slot.setTags(new HashSet<>(Arrays.asList("test", "test2"))); + assertEquals(slot.getTags(), new HashSet<>(Arrays.asList("test", "test2"))); + slot.setTags(null); + assertEquals(slot.getTags(), new HashSet<>(Arrays.asList("test", "test2"))); + } + + @Test + public void setDuration() { + assertEquals(slot.getDuration(), slot.getDuration()); + assertNotEquals(slot.getDuration(), 0); + + slot.setDuration(0); + assertEquals(slot.getDuration(), slotNull.getDuration()); + } + + @Test + public void equals() { + assertEquals(slot, slot); + assertEquals(slotNull, slotNull); + assertEquals(slot.hashCode(), slot.hashCode()); + assertEquals(slotNull.hashCode(), slotNull.hashCode()); + + assertNotEquals(slot, slotNull); + } +} diff --git a/test/java/planmysem/model/VersionedPlannerTest.java b/test/java/planmysem/model/VersionedPlannerTest.java new file mode 100644 index 000000000..ee4ca87fc --- /dev/null +++ b/test/java/planmysem/model/VersionedPlannerTest.java @@ -0,0 +1,95 @@ +package planmysem.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import java.time.LocalDate; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import planmysem.common.Clock; +import planmysem.model.semester.Semester; +import planmysem.model.slot.Slot; +import planmysem.testutil.SlotBuilder; + +public class VersionedPlannerTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setup() { + Clock.set("2019-01-14T10:00:00Z"); + } + + @Test + public void initTest() { + Planner planner = new Planner(); + VersionedPlanner versionedPlanner = new VersionedPlanner(planner); + assertEquals(versionedPlanner.getSemester(), planner.getSemester()); + } + + @Test + public void undo() throws Semester.DateNotFoundException { + VersionedPlanner versionedPlanner = new VersionedPlanner(new Planner()); + Slot slot = new SlotBuilder().slotOne(); + LocalDate date = LocalDate.of(2019, 1, 15); + versionedPlanner.addSlot(date, slot); + versionedPlanner.commit(); + versionedPlanner.undo(); + + VersionedPlanner expectedPlanner = new VersionedPlanner(new Planner()); + + assertEquals(versionedPlanner.getSemester(), expectedPlanner.getSemester()); + } + + @Test + public void undo_throwsNoUndoableStateException() { + VersionedPlanner versionedPlanner = new VersionedPlanner(new Planner()); + + thrown.expect(VersionedPlanner.NoUndoableStateException.class); + versionedPlanner.undo(); + } + + @Test + public void redo() throws Semester.DateNotFoundException { + VersionedPlanner versionedPlanner = new VersionedPlanner(new Planner()); + Slot slot = new SlotBuilder().slotOne(); + LocalDate date = LocalDate.of(2019, 1, 15); + versionedPlanner.addSlot(date, slot); + versionedPlanner.commit(); + versionedPlanner.undo(); + versionedPlanner.redo(); + + VersionedPlanner expectedPlanner = new VersionedPlanner(new Planner()); + expectedPlanner.addSlot(date, slot); + + assertEquals(versionedPlanner.getSemester(), expectedPlanner.getSemester()); + } + + @Test + public void redo_throwsNoRedoableStateException() { + VersionedPlanner versionedPlanner = new VersionedPlanner(new Planner()); + + thrown.expect(VersionedPlanner.NoRedoableStateException.class); + versionedPlanner.redo(); + } + + @Test + public void equals() { + VersionedPlanner versionedPlanner = new VersionedPlanner(new Planner()); + VersionedPlanner expectedPlanner = new VersionedPlanner(new Planner()); + + // equals same object + assertEquals(versionedPlanner, versionedPlanner); + assertEquals(versionedPlanner.hashCode(), versionedPlanner.hashCode()); + + // equals null + assertNotEquals(versionedPlanner, null); + + // different objects same values + assertEquals(versionedPlanner, expectedPlanner); + assertEquals(versionedPlanner.hashCode(), expectedPlanner.hashCode()); + } +} diff --git a/test/java/planmysem/storage/StorageFileTest.java b/test/java/planmysem/storage/StorageFileTest.java index 9ab1b32c4..0f43d6365 100644 --- a/test/java/planmysem/storage/StorageFileTest.java +++ b/test/java/planmysem/storage/StorageFileTest.java @@ -1,14 +1,19 @@ package planmysem.storage; -import static planmysem.util.TestUtil.assertTextFilesEqual; - -import java.nio.file.Paths; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.Arrays; +import java.util.HashSet; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; +import planmysem.common.Clock; import planmysem.common.exceptions.IllegalValueException; +import planmysem.model.Planner; +import planmysem.model.slot.Slot; public class StorageFileTest { private static final String TEST_DATA_FOLDER = "test/model/StorageFileTest"; @@ -19,6 +24,11 @@ public class StorageFileTest { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Before + public void setup() { + Clock.set("2019-01-14T10:00:00Z"); + } + @Test public void constructor_nullFilePath_exceptionThrown() throws Exception { thrown.expect(NullPointerException.class); @@ -31,48 +41,37 @@ public void constructor_noTxtExtension_exceptionThrown() throws Exception { new StorageFile(TEST_DATA_FOLDER + "/" + "InvalidfileName"); } - @Test - public void load_invalidFormat_exceptionThrown() throws Exception { - // The file contains valid xml model, but does not match the Planner class - StorageFile storage = getStorage("InvalidData.txt"); - thrown.expect(StorageFile.StorageOperationException.class); - storage.load(); - } + // @Test + // public void load_invalidData_ThrowIllegalBlockSizeException() throws Exception { + // StorageFile storage = getStorage("InvalidData.txt"); + // thrown.expect(Storage.StorageOperationException.class); + // storage.load(); + // } // @Test // public void load_validFormat() throws Exception { - // AddressBook actualAB = getStorage("ValidData.txt").load(); - // AddressBook expectedAB = getTestAddressBook(); + // Planner actualPlanner = getStorage(TEST_DATA_FOLDER + "/" +"ValidData.txt").load(); + // Planner expectedPlanner = getTestPlanner(); // - // // ensure loaded AddressBook is properly constructed with test model - // // TODO: overwrite equals method in AddressBook class and replace with equals method below - // assertEquals(actualAB.getAllPersons(), expectedAB.getAllPersons()); + // assertEquals(actualPlanner.getSemester(), expectedPlanner.getSemester()); // } - // - // @Test - // public void save_nullAddressBook_exceptionThrown() throws Exception { - // StorageFile storage = getTempStorage(); - // thrown.expect(NullPointerException.class); - // storage.save(null); - // } - // + + @Test + public void save_nullPlanner_exceptionThrown() throws Exception { + StorageFile storage = getTempStorage(); + thrown.expect(NullPointerException.class); + storage.save(null); + } + // @Test - // public void save_validAddressBook() throws Exception { - // AddressBook ab = getTestAddressBook(); + // public void save_validPlanner() throws Exception { + // Planner actualPlanner = getTestPlanner(); // StorageFile storage = getTempStorage(); - // storage.save(ab); + // storage.save(actualPlanner); // - // assertStorageFilesEqual(storage, getStorage("ValidData.txt")); + // assertEquals(storage.load().getSemester(), + // getStorage(TEST_DATA_FOLDER + "/" +"ValidData.txt").load().getSemester()); // } - // - // // getPath() method in StorageFile class is trivial so it is not tested - // - /** - * Asserts that the contents of two storage files are the same. - */ - private void assertStorageFilesEqual(StorageFile sf1, StorageFile sf2) throws Exception { - assertTextFilesEqual(Paths.get(sf1.getPath()), Paths.get(sf2.getPath())); - } private StorageFile getStorage(String fileName) throws Exception { return new StorageFile(TEST_DATA_FOLDER + "/" + fileName); @@ -82,18 +81,29 @@ private StorageFile getTempStorage() throws Exception { return new StorageFile(temporaryFolder.getRoot().getPath() + "/" + "temp.txt"); } - // private Planner getTestAddressBook() throws Exception { - // Planner planner = new Planner(); - // planner.addPerson(new Person(new Name("John Doe"), - // new Phone("98765432", false), - // new Email("johnd@gmail.com", false), - // new Address("John street, block 123, #01-01", false), - // Collections.emptySet())); - // planner.addPerson(new Person(new Name("Betsy Crowe"), - // new Phone("1234567", true), - // new Email("betsycrowe@gmail.com", false), - // new Address("Newgate Prison", true), - // new HashSet<>(Arrays.asList(new Tag("friend"), new Tag("criminal"))))); - // return planner; - // } + private Planner getTestPlanner() throws Exception { + Planner planner = new Planner(); + + planner.addSlot(LocalDate.of(2019, 4, 5), + new Slot("CS2113T Tutorial", + null, + "Topic: Sequence Diagram", + LocalTime.of(8, 0), + 60, + new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) + ) + ); + + planner.addSlot(LocalDate.of(2019, 4, 8), + new Slot("CS2113T Tutorial", + null, + "Topic: Sequence Diagram", + LocalTime.of(8, 0), + 60, + new HashSet<>(Arrays.asList("CS2113T", "Tutorial")) + ) + ); + + return planner; + } } diff --git a/test/java/planmysem/testutil/SlotBuilder.java b/test/java/planmysem/testutil/SlotBuilder.java index b68d246c8..144339e17 100644 --- a/test/java/planmysem/testutil/SlotBuilder.java +++ b/test/java/planmysem/testutil/SlotBuilder.java @@ -7,25 +7,44 @@ import java.util.Set; import java.util.StringJoiner; -import planmysem.common.Utils; import planmysem.model.recurrence.Recurrence; import planmysem.model.slot.Slot; /** * A utility class to generate test data. */ -public class SlotBuilder{ +public class SlotBuilder { + /** + * Generates a generic slot. + */ public Slot slotOne() { String name = "CS2113T Tutorial"; String location = "COM2 04-11"; String description = "Topic: Sequence Diagram"; LocalTime startTime = LocalTime.parse("08:00"); LocalTime endTime = LocalTime.parse("09:00"); - Set tags = new HashSet<>(Arrays.asList( "CS2113T", "Tutorial")); + Set tags = new HashSet<>(Arrays.asList("CS2113T", "Tutorial")); return new Slot(name, location, description, startTime, endTime, tags); } + /** + * Generates a slot full of null values. + */ + public Slot slotNull() { + return new Slot( + "slotNull", + null, + null, + LocalTime.parse("00:00"), + 0, + null + ); + } + + /** + * Generates a generic recurrence object. + */ public Recurrence recurrenceOne() { return new Recurrence( new HashSet<>(Arrays.asList("CS2113T", "Tutorial")), @@ -40,7 +59,7 @@ public Recurrence recurrenceOne() { * * @param seed used to generate the person data field values */ - public Slot generateSlot(int seed) throws Exception { + public Slot generateSlot(int seed) { return new Slot( "slot " + seed, "location " + Math.abs(seed), @@ -52,36 +71,7 @@ public Slot generateSlot(int seed) throws Exception { } /** Generates the correct add command based on the person given */ - String generateAddCommand(Slot s, LocalDate date, String recurrence) { - StringJoiner cmd = new StringJoiner(" "); - - cmd.add("add"); - - cmd.add("n/" + s.getName()); - cmd.add("d/" + Utils.parseDate(date)); - cmd.add("st/" + s.getStartTime()); - cmd.add("et/" + s.getDuration()); - if (s.getLocation() != null) { - cmd.add("l/" + s.getLocation()); - } - if (s.getDescription() != null) { - cmd.add("des/" + s.getDescription()); - } - - Set tags = s.getTags(); - if (tags != null) { - for(String tag : tags){ - cmd.add("t/" + tag); - } - } - - cmd.add(recurrence); - - return cmd.toString(); - } - - /** Generates the correct add command based on the person given */ - String generateAddCommand(Slot s, int day, String recurrence) { + public static String generateAddCommand(Slot s, int day, String recurrence) { StringJoiner cmd = new StringJoiner(" "); cmd.add("add"); @@ -109,34 +99,4 @@ String generateAddCommand(Slot s, int day, String recurrence) { return cmd.toString(); } - /** Generates the correct delete command based on tags */ - String generateDeleteCommand(Set tags) { - StringJoiner cmd = new StringJoiner(" "); - - cmd.add("delete"); - - if (tags != null) { - for(String tag : tags){ - cmd.add("t/" + tag); - } - } - - return cmd.toString(); - } - - /** Generates the correct delete command based on the slot. */ - String generateDeleteCommand(Slot slot) { - StringJoiner cmd = new StringJoiner(" "); - - cmd.add("delete"); - - Set tags = slot.getTags(); - if (tags != null) { - for(String tag : tags){ - cmd.add("t/" + tag); - } - } - - return cmd.toString(); - } -} \ No newline at end of file +} diff --git a/test/java/planmysem/util/TestUtil.java b/test/java/planmysem/util/TestUtil.java index 21f9cff11..626946b9f 100644 --- a/test/java/planmysem/util/TestUtil.java +++ b/test/java/planmysem/util/TestUtil.java @@ -8,6 +8,9 @@ import java.nio.file.Path; import java.util.List; +/** + * Contains static methods to be shared. + */ public class TestUtil { /** * Asserts whether the text in the two given files are the same. Ignores any diff --git a/test/model/StorageFileTest/InvalidData.txt b/test/model/StorageFileTest/InvalidData.txt new file mode 100644 index 000000000..874ee0581 --- /dev/null +++ b/test/model/StorageFileTest/InvalidData.txt @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/test/model/StorageFileTest/ValidData.txt b/test/model/StorageFileTest/ValidData.txt new file mode 100644 index 000000000..03321e790 --- /dev/null +++ b/test/model/StorageFileTest/ValidData.txt @@ -0,0 +1 @@ +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 \ No newline at end of file