diff --git a/.classpath b/.classpath
new file mode 100644
index 00000000000..a86fcbcef21
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000000..819f65e6682
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,1339 @@
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = false
+max_line_length = 120
+tab_width = 4
+ij_continuation_indent_size = 8
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = false
+ij_smart_tabs = false
+ij_visual_guides = 110,120
+ij_wrap_on_typing = true
+
+[*.css]
+ij_css_align_closing_brace_with_properties = false
+ij_css_blank_lines_around_nested_selector = 1
+ij_css_blank_lines_between_blocks = 1
+ij_css_brace_placement = 0
+ij_css_enforce_quotes_on_format = false
+ij_css_hex_color_long_format = false
+ij_css_hex_color_lower_case = false
+ij_css_hex_color_short_format = false
+ij_css_hex_color_upper_case = false
+ij_css_keep_blank_lines_in_code = 2
+ij_css_keep_indents_on_empty_lines = false
+ij_css_keep_single_line_blocks = false
+ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_css_space_after_colon = true
+ij_css_space_before_opening_brace = true
+ij_css_use_double_quotes = true
+ij_css_value_alignment = 0
+
+[*.feature]
+indent_size = 2
+ij_gherkin_keep_indents_on_empty_lines = false
+
+[*.gsp]
+ij_gsp_keep_indents_on_empty_lines = false
+
+[*.haml]
+indent_size = 2
+ij_haml_keep_indents_on_empty_lines = false
+
+[*.java]
+ij_continuation_indent_size = 4
+ij_wrap_on_typing = false
+ij_java_align_consecutive_assignments = false
+ij_java_align_consecutive_variable_declarations = false
+ij_java_align_group_field_declarations = false
+ij_java_align_multiline_annotation_parameters = false
+ij_java_align_multiline_array_initializer_expression = false
+ij_java_align_multiline_assignment = false
+ij_java_align_multiline_binary_operation = false
+ij_java_align_multiline_chained_methods = false
+ij_java_align_multiline_extends_list = false
+ij_java_align_multiline_for = false
+ij_java_align_multiline_method_parentheses = false
+ij_java_align_multiline_parameters = false
+ij_java_align_multiline_parameters_in_calls = false
+ij_java_align_multiline_parenthesized_expression = false
+ij_java_align_multiline_resources = true
+ij_java_align_multiline_ternary_operation = false
+ij_java_align_multiline_text_blocks = false
+ij_java_align_multiline_throws_list = false
+ij_java_align_subsequent_simple_methods = true
+ij_java_align_throws_keyword = false
+ij_java_annotation_parameter_wrap = on_every_item
+ij_java_array_initializer_new_line_after_left_brace = false
+ij_java_array_initializer_right_brace_on_new_line = false
+ij_java_array_initializer_wrap = normal
+ij_java_assert_statement_colon_on_next_line = false
+ij_java_assert_statement_wrap = normal
+ij_java_assignment_wrap = normal
+ij_java_binary_operation_sign_on_next_line = true
+ij_java_binary_operation_wrap = normal
+ij_java_blank_lines_after_anonymous_class_header = 0
+ij_java_blank_lines_after_class_header = 0
+ij_java_blank_lines_after_imports = 1
+ij_java_blank_lines_after_package = 1
+ij_java_blank_lines_around_class = 1
+ij_java_blank_lines_around_field = 0
+ij_java_blank_lines_around_field_in_interface = 0
+ij_java_blank_lines_around_initializer = 1
+ij_java_blank_lines_around_method = 1
+ij_java_blank_lines_around_method_in_interface = 1
+ij_java_blank_lines_before_class_end = 0
+ij_java_blank_lines_before_imports = 1
+ij_java_blank_lines_before_method_body = 0
+ij_java_blank_lines_before_package = 0
+ij_java_block_brace_style = end_of_line
+ij_java_block_comment_at_first_column = true
+ij_java_call_parameters_new_line_after_left_paren = false
+ij_java_call_parameters_right_paren_on_new_line = true
+ij_java_call_parameters_wrap = normal
+ij_java_case_statement_on_separate_line = true
+ij_java_catch_on_new_line = false
+ij_java_class_annotation_wrap = split_into_lines
+ij_java_class_brace_style = end_of_line
+ij_java_class_count_to_use_import_on_demand = 999
+ij_java_class_names_in_javadoc = 1
+ij_java_do_not_indent_top_level_class_members = false
+ij_java_do_not_wrap_after_single_annotation = false
+ij_java_do_while_brace_force = always
+ij_java_doc_add_blank_line_after_description = true
+ij_java_doc_add_blank_line_after_param_comments = false
+ij_java_doc_add_blank_line_after_return = false
+ij_java_doc_add_p_tag_on_empty_lines = true
+ij_java_doc_align_exception_comments = true
+ij_java_doc_align_param_comments = true
+ij_java_doc_do_not_wrap_if_one_line = false
+ij_java_doc_enable_formatting = true
+ij_java_doc_enable_leading_asterisks = true
+ij_java_doc_indent_on_continuation = false
+ij_java_doc_keep_empty_lines = true
+ij_java_doc_keep_empty_parameter_tag = true
+ij_java_doc_keep_empty_return_tag = true
+ij_java_doc_keep_empty_throws_tag = true
+ij_java_doc_keep_invalid_tags = true
+ij_java_doc_param_description_on_new_line = false
+ij_java_doc_preserve_line_breaks = false
+ij_java_doc_use_throws_not_exception_tag = true
+ij_java_else_on_new_line = false
+ij_java_entity_dd_suffix = EJB
+ij_java_entity_eb_suffix = Bean
+ij_java_entity_hi_suffix = Home
+ij_java_entity_lhi_prefix = Local
+ij_java_entity_lhi_suffix = Home
+ij_java_entity_li_prefix = Local
+ij_java_entity_pk_class = java.lang.String
+ij_java_entity_vo_suffix = VO
+ij_java_enum_constants_wrap = split_into_lines
+ij_java_extends_keyword_wrap = normal
+ij_java_extends_list_wrap = normal
+ij_java_field_annotation_wrap = split_into_lines
+ij_java_finally_on_new_line = false
+ij_java_for_brace_force = always
+ij_java_for_statement_new_line_after_left_paren = false
+ij_java_for_statement_right_paren_on_new_line = false
+ij_java_for_statement_wrap = normal
+ij_java_generate_final_locals = false
+ij_java_generate_final_parameters = false
+ij_java_if_brace_force = always
+ij_java_imports_layout = $*,|,java.**,javax.**,|,org.**,|,com.**,|,*
+ij_java_indent_case_from_switch = false
+ij_java_insert_inner_class_imports = false
+ij_java_insert_override_annotation = true
+ij_java_keep_blank_lines_before_right_brace = 2
+ij_java_keep_blank_lines_between_package_declaration_and_header = 2
+ij_java_keep_blank_lines_in_code = 2
+ij_java_keep_blank_lines_in_declarations = 1
+ij_java_keep_control_statement_in_one_line = false
+ij_java_keep_first_column_comment = false
+ij_java_keep_indents_on_empty_lines = false
+ij_java_keep_line_breaks = true
+ij_java_keep_multiple_expressions_in_one_line = false
+ij_java_keep_simple_blocks_in_one_line = false
+ij_java_keep_simple_classes_in_one_line = false
+ij_java_keep_simple_lambdas_in_one_line = false
+ij_java_keep_simple_methods_in_one_line = false
+ij_java_label_indent_absolute = false
+ij_java_label_indent_size = 0
+ij_java_lambda_brace_style = next_line_if_wrapped
+ij_java_layout_static_imports_separately = true
+ij_java_line_comment_add_space = true
+ij_java_line_comment_at_first_column = false
+ij_java_message_dd_suffix = EJB
+ij_java_message_eb_suffix = Bean
+ij_java_method_annotation_wrap = split_into_lines
+ij_java_method_brace_style = end_of_line
+ij_java_method_call_chain_wrap = normal
+ij_java_method_parameters_new_line_after_left_paren = false
+ij_java_method_parameters_right_paren_on_new_line = false
+ij_java_method_parameters_wrap = normal
+ij_java_modifier_list_wrap = false
+ij_java_names_count_to_use_import_on_demand = 999
+ij_java_parameter_annotation_wrap = on_every_item
+ij_java_parentheses_expression_new_line_after_left_paren = false
+ij_java_parentheses_expression_right_paren_on_new_line = false
+ij_java_place_assignment_sign_on_next_line = false
+ij_java_prefer_longer_names = true
+ij_java_prefer_parameters_wrap = false
+ij_java_repeat_synchronized = true
+ij_java_replace_instanceof_and_cast = false
+ij_java_replace_null_check = true
+ij_java_replace_sum_lambda_with_method_ref = true
+ij_java_resource_list_new_line_after_left_paren = false
+ij_java_resource_list_right_paren_on_new_line = false
+ij_java_resource_list_wrap = normal
+ij_java_session_dd_suffix = EJB
+ij_java_session_eb_suffix = Bean
+ij_java_session_hi_suffix = Home
+ij_java_session_lhi_prefix = Local
+ij_java_session_lhi_suffix = Home
+ij_java_session_li_prefix = Local
+ij_java_session_si_suffix = Service
+ij_java_space_after_closing_angle_bracket_in_type_argument = false
+ij_java_space_after_colon = true
+ij_java_space_after_comma = true
+ij_java_space_after_comma_in_type_arguments = true
+ij_java_space_after_for_semicolon = true
+ij_java_space_after_quest = true
+ij_java_space_after_type_cast = true
+ij_java_space_before_annotation_array_initializer_left_brace = false
+ij_java_space_before_annotation_parameter_list = false
+ij_java_space_before_array_initializer_left_brace = false
+ij_java_space_before_catch_keyword = true
+ij_java_space_before_catch_left_brace = true
+ij_java_space_before_catch_parentheses = true
+ij_java_space_before_class_left_brace = true
+ij_java_space_before_colon = true
+ij_java_space_before_colon_in_foreach = true
+ij_java_space_before_comma = false
+ij_java_space_before_do_left_brace = true
+ij_java_space_before_else_keyword = true
+ij_java_space_before_else_left_brace = true
+ij_java_space_before_finally_keyword = true
+ij_java_space_before_finally_left_brace = true
+ij_java_space_before_for_left_brace = true
+ij_java_space_before_for_parentheses = true
+ij_java_space_before_for_semicolon = false
+ij_java_space_before_if_left_brace = true
+ij_java_space_before_if_parentheses = true
+ij_java_space_before_method_call_parentheses = false
+ij_java_space_before_method_left_brace = true
+ij_java_space_before_method_parentheses = false
+ij_java_space_before_opening_angle_bracket_in_type_parameter = false
+ij_java_space_before_quest = true
+ij_java_space_before_switch_left_brace = true
+ij_java_space_before_switch_parentheses = true
+ij_java_space_before_synchronized_left_brace = true
+ij_java_space_before_synchronized_parentheses = true
+ij_java_space_before_try_left_brace = true
+ij_java_space_before_try_parentheses = true
+ij_java_space_before_type_parameter_list = false
+ij_java_space_before_while_keyword = true
+ij_java_space_before_while_left_brace = true
+ij_java_space_before_while_parentheses = true
+ij_java_space_inside_one_line_enum_braces = false
+ij_java_space_within_empty_array_initializer_braces = false
+ij_java_space_within_empty_method_call_parentheses = false
+ij_java_space_within_empty_method_parentheses = false
+ij_java_spaces_around_additive_operators = true
+ij_java_spaces_around_assignment_operators = true
+ij_java_spaces_around_bitwise_operators = true
+ij_java_spaces_around_equality_operators = true
+ij_java_spaces_around_lambda_arrow = true
+ij_java_spaces_around_logical_operators = true
+ij_java_spaces_around_method_ref_dbl_colon = false
+ij_java_spaces_around_multiplicative_operators = true
+ij_java_spaces_around_relational_operators = true
+ij_java_spaces_around_shift_operators = true
+ij_java_spaces_around_type_bounds_in_type_parameters = true
+ij_java_spaces_around_unary_operator = false
+ij_java_spaces_within_angle_brackets = false
+ij_java_spaces_within_annotation_parentheses = false
+ij_java_spaces_within_array_initializer_braces = false
+ij_java_spaces_within_braces = false
+ij_java_spaces_within_brackets = false
+ij_java_spaces_within_cast_parentheses = false
+ij_java_spaces_within_catch_parentheses = false
+ij_java_spaces_within_for_parentheses = false
+ij_java_spaces_within_if_parentheses = false
+ij_java_spaces_within_method_call_parentheses = false
+ij_java_spaces_within_method_parentheses = false
+ij_java_spaces_within_parentheses = false
+ij_java_spaces_within_switch_parentheses = false
+ij_java_spaces_within_synchronized_parentheses = false
+ij_java_spaces_within_try_parentheses = false
+ij_java_spaces_within_while_parentheses = false
+ij_java_special_else_if_treatment = true
+ij_java_subclass_name_suffix = Impl
+ij_java_ternary_operation_signs_on_next_line = false
+ij_java_ternary_operation_wrap = normal
+ij_java_test_name_suffix = Test
+ij_java_throws_keyword_wrap = normal
+ij_java_throws_list_wrap = normal
+ij_java_use_external_annotations = false
+ij_java_use_fq_class_names = false
+ij_java_use_relative_indents = true
+ij_java_use_single_class_imports = true
+ij_java_variable_annotation_wrap = normal
+ij_java_visibility = public
+ij_java_while_brace_force = always
+ij_java_while_on_new_line = false
+ij_java_wrap_comments = false
+ij_java_wrap_first_method_in_call_chain = false
+ij_java_wrap_long_lines = true
+
+[*.less]
+indent_size = 2
+ij_less_align_closing_brace_with_properties = false
+ij_less_blank_lines_around_nested_selector = 1
+ij_less_blank_lines_between_blocks = 1
+ij_less_brace_placement = 0
+ij_less_enforce_quotes_on_format = false
+ij_less_hex_color_long_format = false
+ij_less_hex_color_lower_case = false
+ij_less_hex_color_short_format = false
+ij_less_hex_color_upper_case = false
+ij_less_keep_blank_lines_in_code = 2
+ij_less_keep_indents_on_empty_lines = false
+ij_less_keep_single_line_blocks = false
+ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_less_space_after_colon = true
+ij_less_space_before_opening_brace = true
+ij_less_use_double_quotes = true
+ij_less_value_alignment = 0
+
+[*.sass]
+indent_size = 2
+ij_sass_align_closing_brace_with_properties = false
+ij_sass_blank_lines_around_nested_selector = 1
+ij_sass_blank_lines_between_blocks = 1
+ij_sass_brace_placement = 0
+ij_sass_enforce_quotes_on_format = false
+ij_sass_hex_color_long_format = false
+ij_sass_hex_color_lower_case = false
+ij_sass_hex_color_short_format = false
+ij_sass_hex_color_upper_case = false
+ij_sass_keep_blank_lines_in_code = 2
+ij_sass_keep_indents_on_empty_lines = false
+ij_sass_keep_single_line_blocks = false
+ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_sass_space_after_colon = true
+ij_sass_space_before_opening_brace = true
+ij_sass_use_double_quotes = true
+ij_sass_value_alignment = 0
+
+[*.scss]
+indent_size = 2
+ij_scss_align_closing_brace_with_properties = false
+ij_scss_blank_lines_around_nested_selector = 1
+ij_scss_blank_lines_between_blocks = 1
+ij_scss_brace_placement = 0
+ij_scss_enforce_quotes_on_format = false
+ij_scss_hex_color_long_format = false
+ij_scss_hex_color_lower_case = false
+ij_scss_hex_color_short_format = false
+ij_scss_hex_color_upper_case = false
+ij_scss_keep_blank_lines_in_code = 2
+ij_scss_keep_indents_on_empty_lines = false
+ij_scss_keep_single_line_blocks = false
+ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_scss_space_after_colon = true
+ij_scss_space_before_opening_brace = true
+ij_scss_use_double_quotes = true
+ij_scss_value_alignment = 0
+
+[*.styl]
+indent_size = 2
+ij_stylus_align_closing_brace_with_properties = false
+ij_stylus_blank_lines_around_nested_selector = 1
+ij_stylus_blank_lines_between_blocks = 1
+ij_stylus_brace_placement = 0
+ij_stylus_enforce_quotes_on_format = false
+ij_stylus_hex_color_long_format = false
+ij_stylus_hex_color_lower_case = false
+ij_stylus_hex_color_short_format = false
+ij_stylus_hex_color_upper_case = false
+ij_stylus_keep_blank_lines_in_code = 2
+ij_stylus_keep_indents_on_empty_lines = false
+ij_stylus_keep_single_line_blocks = false
+ij_stylus_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_stylus_space_after_colon = true
+ij_stylus_space_before_opening_brace = true
+ij_stylus_use_double_quotes = true
+ij_stylus_value_alignment = 0
+
+[.editorconfig]
+ij_editorconfig_align_group_field_declarations = false
+ij_editorconfig_space_after_colon = false
+ij_editorconfig_space_after_comma = true
+ij_editorconfig_space_before_colon = false
+ij_editorconfig_space_before_comma = false
+ij_editorconfig_spaces_around_assignment_operators = true
+
+[{*.as,*.js2,*.es}]
+ij_actionscript_align_imports = false
+ij_actionscript_align_multiline_array_initializer_expression = false
+ij_actionscript_align_multiline_binary_operation = false
+ij_actionscript_align_multiline_chained_methods = false
+ij_actionscript_align_multiline_extends_list = false
+ij_actionscript_align_multiline_for = true
+ij_actionscript_align_multiline_parameters = true
+ij_actionscript_align_multiline_parameters_in_calls = false
+ij_actionscript_align_multiline_ternary_operation = false
+ij_actionscript_align_object_properties = 0
+ij_actionscript_align_union_types = false
+ij_actionscript_align_var_statements = 0
+ij_actionscript_array_initializer_new_line_after_left_brace = false
+ij_actionscript_array_initializer_right_brace_on_new_line = false
+ij_actionscript_array_initializer_wrap = off
+ij_actionscript_assignment_wrap = off
+ij_actionscript_binary_operation_sign_on_next_line = false
+ij_actionscript_binary_operation_wrap = off
+ij_actionscript_blacklist_imports = rxjs/Rx,node_modules/**/*,@angular/material,@angular/material/typings/**,~/node_modules/**/*,@/node_modules/**/*
+ij_actionscript_blank_lines_after_imports = 1
+ij_actionscript_blank_lines_after_package = 0
+ij_actionscript_blank_lines_around_function = 1
+ij_actionscript_blank_lines_around_method = 1
+ij_actionscript_blank_lines_before_imports = 1
+ij_actionscript_blank_lines_before_package = 0
+ij_actionscript_block_brace_style = end_of_line
+ij_actionscript_call_parameters_new_line_after_left_paren = false
+ij_actionscript_call_parameters_right_paren_on_new_line = false
+ij_actionscript_call_parameters_wrap = off
+ij_actionscript_catch_on_new_line = false
+ij_actionscript_chained_call_dot_on_new_line = true
+ij_actionscript_class_brace_style = end_of_line
+ij_actionscript_comma_on_new_line = false
+ij_actionscript_do_while_brace_force = never
+ij_actionscript_else_on_new_line = false
+ij_actionscript_enforce_trailing_comma = keep
+ij_actionscript_extends_keyword_wrap = off
+ij_actionscript_extends_list_wrap = off
+ij_actionscript_field_prefix = _
+ij_actionscript_file_name_style = relaxed
+ij_actionscript_finally_on_new_line = false
+ij_actionscript_for_brace_force = never
+ij_actionscript_for_statement_new_line_after_left_paren = false
+ij_actionscript_for_statement_right_paren_on_new_line = false
+ij_actionscript_for_statement_wrap = off
+ij_actionscript_force_quote_style = false
+ij_actionscript_force_semicolon_style = false
+ij_actionscript_function_expression_brace_style = end_of_line
+ij_actionscript_if_brace_force = never
+ij_actionscript_import_merge_members = global
+ij_actionscript_import_prefer_absolute_path = global
+ij_actionscript_import_sort_members = true
+ij_actionscript_import_sort_module_name = false
+ij_actionscript_import_use_node_resolution = true
+ij_actionscript_imports_wrap = on_every_item
+ij_actionscript_indent_case_from_switch = true
+ij_actionscript_indent_chained_calls = true
+ij_actionscript_indent_package_children = 0
+ij_actionscript_jsx_attribute_value = braces
+ij_actionscript_keep_blank_lines_in_code = 2
+ij_actionscript_keep_first_column_comment = true
+ij_actionscript_keep_indents_on_empty_lines = false
+ij_actionscript_keep_line_breaks = true
+ij_actionscript_keep_simple_blocks_in_one_line = false
+ij_actionscript_keep_simple_methods_in_one_line = false
+ij_actionscript_line_comment_at_first_column = true
+ij_actionscript_method_brace_style = end_of_line
+ij_actionscript_method_call_chain_wrap = off
+ij_actionscript_method_parameters_new_line_after_left_paren = false
+ij_actionscript_method_parameters_right_paren_on_new_line = false
+ij_actionscript_method_parameters_wrap = off
+ij_actionscript_object_literal_wrap = on_every_item
+ij_actionscript_parentheses_expression_new_line_after_left_paren = false
+ij_actionscript_parentheses_expression_right_paren_on_new_line = false
+ij_actionscript_place_assignment_sign_on_next_line = false
+ij_actionscript_prefer_as_type_cast = false
+ij_actionscript_prefer_parameters_wrap = false
+ij_actionscript_reformat_c_style_comments = false
+ij_actionscript_space_after_colon = true
+ij_actionscript_space_after_comma = true
+ij_actionscript_space_after_dots_in_rest_parameter = false
+ij_actionscript_space_after_generator_mult = true
+ij_actionscript_space_after_property_colon = true
+ij_actionscript_space_after_quest = true
+ij_actionscript_space_after_type_colon = false
+ij_actionscript_space_after_unary_not = false
+ij_actionscript_space_before_async_arrow_lparen = true
+ij_actionscript_space_before_catch_keyword = true
+ij_actionscript_space_before_catch_left_brace = true
+ij_actionscript_space_before_catch_parentheses = true
+ij_actionscript_space_before_class_lbrace = true
+ij_actionscript_space_before_colon = true
+ij_actionscript_space_before_comma = false
+ij_actionscript_space_before_do_left_brace = true
+ij_actionscript_space_before_else_keyword = true
+ij_actionscript_space_before_else_left_brace = true
+ij_actionscript_space_before_finally_keyword = true
+ij_actionscript_space_before_finally_left_brace = true
+ij_actionscript_space_before_for_left_brace = true
+ij_actionscript_space_before_for_parentheses = true
+ij_actionscript_space_before_for_semicolon = false
+ij_actionscript_space_before_function_left_parenth = true
+ij_actionscript_space_before_generator_mult = false
+ij_actionscript_space_before_if_left_brace = true
+ij_actionscript_space_before_if_parentheses = true
+ij_actionscript_space_before_method_call_parentheses = false
+ij_actionscript_space_before_method_left_brace = true
+ij_actionscript_space_before_method_parentheses = false
+ij_actionscript_space_before_property_colon = false
+ij_actionscript_space_before_quest = true
+ij_actionscript_space_before_switch_left_brace = true
+ij_actionscript_space_before_switch_parentheses = true
+ij_actionscript_space_before_try_left_brace = true
+ij_actionscript_space_before_type_colon = false
+ij_actionscript_space_before_unary_not = false
+ij_actionscript_space_before_while_keyword = true
+ij_actionscript_space_before_while_left_brace = true
+ij_actionscript_space_before_while_parentheses = true
+ij_actionscript_spaces_around_additive_operators = true
+ij_actionscript_spaces_around_arrow_function_operator = true
+ij_actionscript_spaces_around_assignment_operators = true
+ij_actionscript_spaces_around_bitwise_operators = true
+ij_actionscript_spaces_around_equality_operators = true
+ij_actionscript_spaces_around_logical_operators = true
+ij_actionscript_spaces_around_multiplicative_operators = true
+ij_actionscript_spaces_around_relational_operators = true
+ij_actionscript_spaces_around_shift_operators = true
+ij_actionscript_spaces_around_unary_operator = false
+ij_actionscript_spaces_within_array_initializer_brackets = false
+ij_actionscript_spaces_within_brackets = false
+ij_actionscript_spaces_within_catch_parentheses = false
+ij_actionscript_spaces_within_for_parentheses = false
+ij_actionscript_spaces_within_if_parentheses = false
+ij_actionscript_spaces_within_imports = false
+ij_actionscript_spaces_within_interpolation_expressions = false
+ij_actionscript_spaces_within_method_call_parentheses = false
+ij_actionscript_spaces_within_method_parentheses = false
+ij_actionscript_spaces_within_object_literal_braces = false
+ij_actionscript_spaces_within_object_type_braces = true
+ij_actionscript_spaces_within_parentheses = false
+ij_actionscript_spaces_within_switch_parentheses = false
+ij_actionscript_spaces_within_type_assertion = false
+ij_actionscript_spaces_within_union_types = true
+ij_actionscript_spaces_within_while_parentheses = false
+ij_actionscript_special_else_if_treatment = true
+ij_actionscript_ternary_operation_signs_on_next_line = false
+ij_actionscript_ternary_operation_wrap = off
+ij_actionscript_union_types_wrap = on_every_item
+ij_actionscript_use_chained_calls_group_indents = false
+ij_actionscript_use_double_quotes = true
+ij_actionscript_use_explicit_js_extension = global
+ij_actionscript_use_path_mapping = always
+ij_actionscript_use_public_modifier = false
+ij_actionscript_use_semicolon_after_statement = true
+ij_actionscript_var_declaration_wrap = normal
+ij_actionscript_while_brace_force = never
+ij_actionscript_while_on_new_line = false
+ij_actionscript_wrap_comments = false
+
+[{*.cfml,*.cfm,*.cfc}]
+ij_cfml_align_multiline_binary_operation = false
+ij_cfml_align_multiline_for = true
+ij_cfml_align_multiline_parameters = true
+ij_cfml_align_multiline_parameters_in_calls = false
+ij_cfml_align_multiline_ternary_operation = false
+ij_cfml_assignment_wrap = off
+ij_cfml_binary_operation_sign_on_next_line = false
+ij_cfml_binary_operation_wrap = off
+ij_cfml_block_brace_style = end_of_line
+ij_cfml_call_parameters_new_line_after_left_paren = false
+ij_cfml_call_parameters_right_paren_on_new_line = false
+ij_cfml_call_parameters_wrap = off
+ij_cfml_catch_on_new_line = false
+ij_cfml_else_on_new_line = false
+ij_cfml_for_statement_new_line_after_left_paren = false
+ij_cfml_for_statement_right_paren_on_new_line = false
+ij_cfml_for_statement_wrap = off
+ij_cfml_keep_blank_lines_in_code = 2
+ij_cfml_keep_first_column_comment = true
+ij_cfml_keep_indents_on_empty_lines = false
+ij_cfml_keep_line_breaks = true
+ij_cfml_method_brace_style = next_line
+ij_cfml_method_parameters_new_line_after_left_paren = false
+ij_cfml_method_parameters_right_paren_on_new_line = false
+ij_cfml_method_parameters_wrap = off
+ij_cfml_parentheses_expression_new_line_after_left_paren = false
+ij_cfml_parentheses_expression_right_paren_on_new_line = false
+ij_cfml_place_assignment_sign_on_next_line = false
+ij_cfml_space_after_colon = true
+ij_cfml_space_after_comma = true
+ij_cfml_space_after_for_semicolon = true
+ij_cfml_space_after_quest = true
+ij_cfml_space_before_catch_keyword = true
+ij_cfml_space_before_catch_left_brace = true
+ij_cfml_space_before_catch_parentheses = true
+ij_cfml_space_before_colon = true
+ij_cfml_space_before_comma = false
+ij_cfml_space_before_else_keyword = true
+ij_cfml_space_before_else_left_brace = true
+ij_cfml_space_before_for_left_brace = true
+ij_cfml_space_before_for_parentheses = true
+ij_cfml_space_before_for_semicolon = false
+ij_cfml_space_before_if_left_brace = true
+ij_cfml_space_before_if_parentheses = true
+ij_cfml_space_before_method_call_parentheses = false
+ij_cfml_space_before_method_left_brace = true
+ij_cfml_space_before_method_parentheses = false
+ij_cfml_space_before_quest = true
+ij_cfml_space_before_switch_left_brace = true
+ij_cfml_space_before_switch_parentheses = true
+ij_cfml_space_before_try_left_brace = true
+ij_cfml_space_before_while_keyword = true
+ij_cfml_space_before_while_left_brace = true
+ij_cfml_space_before_while_parentheses = true
+ij_cfml_spaces_around_additive_operators = true
+ij_cfml_spaces_around_assignment_operators = true
+ij_cfml_spaces_around_equality_operators = true
+ij_cfml_spaces_around_logical_operators = true
+ij_cfml_spaces_around_multiplicative_operators = true
+ij_cfml_spaces_around_relational_operators = true
+ij_cfml_spaces_around_unary_operator = false
+ij_cfml_spaces_within_catch_parentheses = false
+ij_cfml_spaces_within_for_parentheses = false
+ij_cfml_spaces_within_if_parentheses = false
+ij_cfml_spaces_within_method_call_parentheses = false
+ij_cfml_spaces_within_method_parentheses = false
+ij_cfml_spaces_within_switch_parentheses = false
+ij_cfml_spaces_within_while_parentheses = false
+ij_cfml_special_else_if_treatment = false
+ij_cfml_ternary_operation_signs_on_next_line = false
+ij_cfml_ternary_operation_wrap = off
+ij_cfml_while_on_new_line = false
+
+[{*.cjs,*.js}]
+ij_continuation_indent_size = 4
+ij_javascript_align_imports = false
+ij_javascript_align_multiline_array_initializer_expression = false
+ij_javascript_align_multiline_binary_operation = false
+ij_javascript_align_multiline_chained_methods = false
+ij_javascript_align_multiline_extends_list = false
+ij_javascript_align_multiline_for = true
+ij_javascript_align_multiline_parameters = true
+ij_javascript_align_multiline_parameters_in_calls = false
+ij_javascript_align_multiline_ternary_operation = false
+ij_javascript_align_object_properties = 0
+ij_javascript_align_union_types = false
+ij_javascript_align_var_statements = 0
+ij_javascript_array_initializer_new_line_after_left_brace = false
+ij_javascript_array_initializer_right_brace_on_new_line = false
+ij_javascript_array_initializer_wrap = off
+ij_javascript_assignment_wrap = off
+ij_javascript_binary_operation_sign_on_next_line = false
+ij_javascript_binary_operation_wrap = off
+ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**/*,@angular/material,@angular/material/typings/**,~/node_modules/**/*,@/node_modules/**/*
+ij_javascript_blank_lines_after_imports = 1
+ij_javascript_blank_lines_around_class = 1
+ij_javascript_blank_lines_around_field = 0
+ij_javascript_blank_lines_around_function = 1
+ij_javascript_blank_lines_around_method = 1
+ij_javascript_block_brace_style = end_of_line
+ij_javascript_call_parameters_new_line_after_left_paren = false
+ij_javascript_call_parameters_right_paren_on_new_line = false
+ij_javascript_call_parameters_wrap = off
+ij_javascript_catch_on_new_line = false
+ij_javascript_chained_call_dot_on_new_line = true
+ij_javascript_class_brace_style = end_of_line
+ij_javascript_comma_on_new_line = false
+ij_javascript_do_while_brace_force = never
+ij_javascript_else_on_new_line = false
+ij_javascript_enforce_trailing_comma = keep
+ij_javascript_extends_keyword_wrap = off
+ij_javascript_extends_list_wrap = off
+ij_javascript_field_prefix = _
+ij_javascript_file_name_style = relaxed
+ij_javascript_finally_on_new_line = false
+ij_javascript_for_brace_force = never
+ij_javascript_for_statement_new_line_after_left_paren = false
+ij_javascript_for_statement_right_paren_on_new_line = false
+ij_javascript_for_statement_wrap = off
+ij_javascript_force_quote_style = false
+ij_javascript_force_semicolon_style = false
+ij_javascript_function_expression_brace_style = end_of_line
+ij_javascript_if_brace_force = never
+ij_javascript_import_merge_members = global
+ij_javascript_import_prefer_absolute_path = global
+ij_javascript_import_sort_members = true
+ij_javascript_import_sort_module_name = false
+ij_javascript_import_use_node_resolution = true
+ij_javascript_imports_wrap = on_every_item
+ij_javascript_indent_case_from_switch = true
+ij_javascript_indent_chained_calls = true
+ij_javascript_indent_package_children = 0
+ij_javascript_jsx_attribute_value = braces
+ij_javascript_keep_blank_lines_in_code = 2
+ij_javascript_keep_first_column_comment = true
+ij_javascript_keep_indents_on_empty_lines = false
+ij_javascript_keep_line_breaks = true
+ij_javascript_keep_simple_blocks_in_one_line = false
+ij_javascript_keep_simple_methods_in_one_line = false
+ij_javascript_line_comment_add_space = true
+ij_javascript_line_comment_at_first_column = false
+ij_javascript_method_brace_style = end_of_line
+ij_javascript_method_call_chain_wrap = off
+ij_javascript_method_parameters_new_line_after_left_paren = false
+ij_javascript_method_parameters_right_paren_on_new_line = false
+ij_javascript_method_parameters_wrap = off
+ij_javascript_object_literal_wrap = on_every_item
+ij_javascript_parentheses_expression_new_line_after_left_paren = false
+ij_javascript_parentheses_expression_right_paren_on_new_line = false
+ij_javascript_place_assignment_sign_on_next_line = false
+ij_javascript_prefer_as_type_cast = false
+ij_javascript_prefer_parameters_wrap = false
+ij_javascript_reformat_c_style_comments = false
+ij_javascript_space_after_colon = true
+ij_javascript_space_after_comma = true
+ij_javascript_space_after_dots_in_rest_parameter = false
+ij_javascript_space_after_generator_mult = true
+ij_javascript_space_after_property_colon = true
+ij_javascript_space_after_quest = true
+ij_javascript_space_after_type_colon = true
+ij_javascript_space_after_unary_not = false
+ij_javascript_space_before_async_arrow_lparen = true
+ij_javascript_space_before_catch_keyword = true
+ij_javascript_space_before_catch_left_brace = true
+ij_javascript_space_before_catch_parentheses = true
+ij_javascript_space_before_class_lbrace = true
+ij_javascript_space_before_class_left_brace = true
+ij_javascript_space_before_colon = true
+ij_javascript_space_before_comma = false
+ij_javascript_space_before_do_left_brace = true
+ij_javascript_space_before_else_keyword = true
+ij_javascript_space_before_else_left_brace = true
+ij_javascript_space_before_finally_keyword = true
+ij_javascript_space_before_finally_left_brace = true
+ij_javascript_space_before_for_left_brace = true
+ij_javascript_space_before_for_parentheses = true
+ij_javascript_space_before_for_semicolon = false
+ij_javascript_space_before_function_left_parenth = true
+ij_javascript_space_before_generator_mult = false
+ij_javascript_space_before_if_left_brace = true
+ij_javascript_space_before_if_parentheses = true
+ij_javascript_space_before_method_call_parentheses = false
+ij_javascript_space_before_method_left_brace = true
+ij_javascript_space_before_method_parentheses = false
+ij_javascript_space_before_property_colon = false
+ij_javascript_space_before_quest = true
+ij_javascript_space_before_switch_left_brace = true
+ij_javascript_space_before_switch_parentheses = true
+ij_javascript_space_before_try_left_brace = true
+ij_javascript_space_before_type_colon = false
+ij_javascript_space_before_unary_not = false
+ij_javascript_space_before_while_keyword = true
+ij_javascript_space_before_while_left_brace = true
+ij_javascript_space_before_while_parentheses = true
+ij_javascript_spaces_around_additive_operators = true
+ij_javascript_spaces_around_arrow_function_operator = true
+ij_javascript_spaces_around_assignment_operators = true
+ij_javascript_spaces_around_bitwise_operators = true
+ij_javascript_spaces_around_equality_operators = true
+ij_javascript_spaces_around_logical_operators = true
+ij_javascript_spaces_around_multiplicative_operators = true
+ij_javascript_spaces_around_relational_operators = true
+ij_javascript_spaces_around_shift_operators = true
+ij_javascript_spaces_around_unary_operator = false
+ij_javascript_spaces_within_array_initializer_brackets = false
+ij_javascript_spaces_within_brackets = false
+ij_javascript_spaces_within_catch_parentheses = false
+ij_javascript_spaces_within_for_parentheses = false
+ij_javascript_spaces_within_if_parentheses = false
+ij_javascript_spaces_within_imports = false
+ij_javascript_spaces_within_interpolation_expressions = false
+ij_javascript_spaces_within_method_call_parentheses = false
+ij_javascript_spaces_within_method_parentheses = false
+ij_javascript_spaces_within_object_literal_braces = false
+ij_javascript_spaces_within_object_type_braces = true
+ij_javascript_spaces_within_parentheses = false
+ij_javascript_spaces_within_switch_parentheses = false
+ij_javascript_spaces_within_type_assertion = false
+ij_javascript_spaces_within_union_types = true
+ij_javascript_spaces_within_while_parentheses = false
+ij_javascript_special_else_if_treatment = true
+ij_javascript_ternary_operation_signs_on_next_line = false
+ij_javascript_ternary_operation_wrap = off
+ij_javascript_union_types_wrap = on_every_item
+ij_javascript_use_chained_calls_group_indents = false
+ij_javascript_use_double_quotes = true
+ij_javascript_use_explicit_js_extension = global
+ij_javascript_use_path_mapping = always
+ij_javascript_use_public_modifier = false
+ij_javascript_use_semicolon_after_statement = true
+ij_javascript_var_declaration_wrap = normal
+ij_javascript_while_brace_force = never
+ij_javascript_while_on_new_line = false
+ij_javascript_wrap_comments = false
+
+[{*.cjsx,*.coffee}]
+indent_size = 2
+tab_width = 2
+ij_continuation_indent_size = 2
+ij_coffeescript_align_function_body = false
+ij_coffeescript_align_imports = false
+ij_coffeescript_align_multiline_array_initializer_expression = true
+ij_coffeescript_align_multiline_parameters = true
+ij_coffeescript_align_multiline_parameters_in_calls = false
+ij_coffeescript_align_object_properties = 0
+ij_coffeescript_align_union_types = false
+ij_coffeescript_align_var_statements = 0
+ij_coffeescript_array_initializer_new_line_after_left_brace = false
+ij_coffeescript_array_initializer_right_brace_on_new_line = false
+ij_coffeescript_array_initializer_wrap = normal
+ij_coffeescript_blacklist_imports = rxjs/Rx,node_modules/**/*,@angular/material,@angular/material/typings/**,~/node_modules/**/*,@/node_modules/**/*
+ij_coffeescript_blank_lines_around_function = 1
+ij_coffeescript_call_parameters_new_line_after_left_paren = false
+ij_coffeescript_call_parameters_right_paren_on_new_line = false
+ij_coffeescript_call_parameters_wrap = normal
+ij_coffeescript_chained_call_dot_on_new_line = true
+ij_coffeescript_comma_on_new_line = false
+ij_coffeescript_enforce_trailing_comma = keep
+ij_coffeescript_field_prefix = _
+ij_coffeescript_file_name_style = relaxed
+ij_coffeescript_force_quote_style = false
+ij_coffeescript_force_semicolon_style = false
+ij_coffeescript_function_expression_brace_style = end_of_line
+ij_coffeescript_import_merge_members = global
+ij_coffeescript_import_prefer_absolute_path = global
+ij_coffeescript_import_sort_members = true
+ij_coffeescript_import_sort_module_name = false
+ij_coffeescript_import_use_node_resolution = true
+ij_coffeescript_imports_wrap = on_every_item
+ij_coffeescript_indent_chained_calls = true
+ij_coffeescript_indent_package_children = 0
+ij_coffeescript_jsx_attribute_value = braces
+ij_coffeescript_keep_blank_lines_in_code = 2
+ij_coffeescript_keep_first_column_comment = true
+ij_coffeescript_keep_indents_on_empty_lines = false
+ij_coffeescript_keep_line_breaks = true
+ij_coffeescript_keep_simple_methods_in_one_line = false
+ij_coffeescript_method_parameters_new_line_after_left_paren = false
+ij_coffeescript_method_parameters_right_paren_on_new_line = false
+ij_coffeescript_method_parameters_wrap = off
+ij_coffeescript_object_literal_wrap = on_every_item
+ij_coffeescript_prefer_as_type_cast = false
+ij_coffeescript_reformat_c_style_comments = false
+ij_coffeescript_space_after_comma = true
+ij_coffeescript_space_after_dots_in_rest_parameter = false
+ij_coffeescript_space_after_generator_mult = true
+ij_coffeescript_space_after_property_colon = true
+ij_coffeescript_space_after_type_colon = true
+ij_coffeescript_space_after_unary_not = false
+ij_coffeescript_space_before_async_arrow_lparen = true
+ij_coffeescript_space_before_class_lbrace = true
+ij_coffeescript_space_before_comma = false
+ij_coffeescript_space_before_function_left_parenth = true
+ij_coffeescript_space_before_generator_mult = false
+ij_coffeescript_space_before_property_colon = false
+ij_coffeescript_space_before_type_colon = false
+ij_coffeescript_space_before_unary_not = false
+ij_coffeescript_spaces_around_additive_operators = true
+ij_coffeescript_spaces_around_arrow_function_operator = true
+ij_coffeescript_spaces_around_assignment_operators = true
+ij_coffeescript_spaces_around_bitwise_operators = true
+ij_coffeescript_spaces_around_equality_operators = true
+ij_coffeescript_spaces_around_logical_operators = true
+ij_coffeescript_spaces_around_multiplicative_operators = true
+ij_coffeescript_spaces_around_relational_operators = true
+ij_coffeescript_spaces_around_shift_operators = true
+ij_coffeescript_spaces_around_unary_operator = false
+ij_coffeescript_spaces_within_array_initializer_braces = false
+ij_coffeescript_spaces_within_array_initializer_brackets = false
+ij_coffeescript_spaces_within_imports = false
+ij_coffeescript_spaces_within_index_brackets = false
+ij_coffeescript_spaces_within_interpolation_expressions = false
+ij_coffeescript_spaces_within_method_call_parentheses = false
+ij_coffeescript_spaces_within_method_parentheses = false
+ij_coffeescript_spaces_within_object_braces = false
+ij_coffeescript_spaces_within_object_literal_braces = false
+ij_coffeescript_spaces_within_object_type_braces = true
+ij_coffeescript_spaces_within_range_brackets = false
+ij_coffeescript_spaces_within_type_assertion = false
+ij_coffeescript_spaces_within_union_types = true
+ij_coffeescript_union_types_wrap = on_every_item
+ij_coffeescript_use_chained_calls_group_indents = false
+ij_coffeescript_use_double_quotes = true
+ij_coffeescript_use_explicit_js_extension = global
+ij_coffeescript_use_path_mapping = always
+ij_coffeescript_use_public_modifier = false
+ij_coffeescript_use_semicolon_after_statement = false
+ij_coffeescript_var_declaration_wrap = normal
+
+[{*.gson,*.gradle,*.groovy,*.gdsl,*.gy,*.gant}]
+ij_groovy_align_group_field_declarations = false
+ij_groovy_align_multiline_array_initializer_expression = false
+ij_groovy_align_multiline_assignment = false
+ij_groovy_align_multiline_binary_operation = false
+ij_groovy_align_multiline_chained_methods = false
+ij_groovy_align_multiline_extends_list = false
+ij_groovy_align_multiline_for = true
+ij_groovy_align_multiline_method_parentheses = false
+ij_groovy_align_multiline_parameters = true
+ij_groovy_align_multiline_parameters_in_calls = false
+ij_groovy_align_multiline_resources = true
+ij_groovy_align_multiline_ternary_operation = false
+ij_groovy_align_multiline_throws_list = false
+ij_groovy_align_throws_keyword = false
+ij_groovy_array_initializer_new_line_after_left_brace = false
+ij_groovy_array_initializer_right_brace_on_new_line = false
+ij_groovy_array_initializer_wrap = off
+ij_groovy_assert_statement_wrap = off
+ij_groovy_assignment_wrap = off
+ij_groovy_binary_operation_wrap = off
+ij_groovy_blank_lines_after_class_header = 0
+ij_groovy_blank_lines_after_imports = 1
+ij_groovy_blank_lines_after_package = 1
+ij_groovy_blank_lines_around_class = 1
+ij_groovy_blank_lines_around_field = 0
+ij_groovy_blank_lines_around_field_in_interface = 0
+ij_groovy_blank_lines_around_method = 1
+ij_groovy_blank_lines_around_method_in_interface = 1
+ij_groovy_blank_lines_before_imports = 1
+ij_groovy_blank_lines_before_method_body = 0
+ij_groovy_blank_lines_before_package = 0
+ij_groovy_block_brace_style = end_of_line
+ij_groovy_block_comment_at_first_column = true
+ij_groovy_call_parameters_new_line_after_left_paren = false
+ij_groovy_call_parameters_right_paren_on_new_line = false
+ij_groovy_call_parameters_wrap = off
+ij_groovy_catch_on_new_line = false
+ij_groovy_class_annotation_wrap = split_into_lines
+ij_groovy_class_brace_style = end_of_line
+ij_groovy_do_while_brace_force = never
+ij_groovy_else_on_new_line = false
+ij_groovy_enum_constants_wrap = off
+ij_groovy_extends_keyword_wrap = off
+ij_groovy_extends_list_wrap = off
+ij_groovy_field_annotation_wrap = split_into_lines
+ij_groovy_finally_on_new_line = false
+ij_groovy_for_brace_force = never
+ij_groovy_for_statement_new_line_after_left_paren = false
+ij_groovy_for_statement_right_paren_on_new_line = false
+ij_groovy_for_statement_wrap = off
+ij_groovy_if_brace_force = never
+ij_groovy_indent_case_from_switch = true
+ij_groovy_keep_blank_lines_before_right_brace = 2
+ij_groovy_keep_blank_lines_in_code = 2
+ij_groovy_keep_blank_lines_in_declarations = 2
+ij_groovy_keep_control_statement_in_one_line = true
+ij_groovy_keep_first_column_comment = true
+ij_groovy_keep_indents_on_empty_lines = false
+ij_groovy_keep_line_breaks = true
+ij_groovy_keep_multiple_expressions_in_one_line = false
+ij_groovy_keep_simple_blocks_in_one_line = false
+ij_groovy_keep_simple_classes_in_one_line = true
+ij_groovy_keep_simple_lambdas_in_one_line = true
+ij_groovy_keep_simple_methods_in_one_line = true
+ij_groovy_label_indent_absolute = false
+ij_groovy_label_indent_size = 0
+ij_groovy_lambda_brace_style = end_of_line
+ij_groovy_line_comment_add_space = false
+ij_groovy_line_comment_at_first_column = true
+ij_groovy_method_annotation_wrap = split_into_lines
+ij_groovy_method_brace_style = end_of_line
+ij_groovy_method_call_chain_wrap = off
+ij_groovy_method_parameters_new_line_after_left_paren = false
+ij_groovy_method_parameters_right_paren_on_new_line = false
+ij_groovy_method_parameters_wrap = off
+ij_groovy_modifier_list_wrap = false
+ij_groovy_parameter_annotation_wrap = off
+ij_groovy_parentheses_expression_new_line_after_left_paren = false
+ij_groovy_parentheses_expression_right_paren_on_new_line = false
+ij_groovy_prefer_parameters_wrap = false
+ij_groovy_resource_list_new_line_after_left_paren = false
+ij_groovy_resource_list_right_paren_on_new_line = false
+ij_groovy_resource_list_wrap = off
+ij_groovy_space_after_colon = true
+ij_groovy_space_after_comma = true
+ij_groovy_space_after_comma_in_type_arguments = true
+ij_groovy_space_after_for_semicolon = true
+ij_groovy_space_after_quest = true
+ij_groovy_space_after_type_cast = true
+ij_groovy_space_before_annotation_parameter_list = false
+ij_groovy_space_before_array_initializer_left_brace = false
+ij_groovy_space_before_catch_keyword = true
+ij_groovy_space_before_catch_left_brace = true
+ij_groovy_space_before_catch_parentheses = true
+ij_groovy_space_before_class_left_brace = true
+ij_groovy_space_before_colon = true
+ij_groovy_space_before_comma = false
+ij_groovy_space_before_do_left_brace = true
+ij_groovy_space_before_else_keyword = true
+ij_groovy_space_before_else_left_brace = true
+ij_groovy_space_before_finally_keyword = true
+ij_groovy_space_before_finally_left_brace = true
+ij_groovy_space_before_for_left_brace = true
+ij_groovy_space_before_for_parentheses = true
+ij_groovy_space_before_for_semicolon = false
+ij_groovy_space_before_if_left_brace = true
+ij_groovy_space_before_if_parentheses = true
+ij_groovy_space_before_method_call_parentheses = false
+ij_groovy_space_before_method_left_brace = true
+ij_groovy_space_before_method_parentheses = false
+ij_groovy_space_before_quest = true
+ij_groovy_space_before_switch_left_brace = true
+ij_groovy_space_before_switch_parentheses = true
+ij_groovy_space_before_synchronized_left_brace = true
+ij_groovy_space_before_synchronized_parentheses = true
+ij_groovy_space_before_try_left_brace = true
+ij_groovy_space_before_try_parentheses = true
+ij_groovy_space_before_while_keyword = true
+ij_groovy_space_before_while_left_brace = true
+ij_groovy_space_before_while_parentheses = true
+ij_groovy_space_within_empty_array_initializer_braces = false
+ij_groovy_space_within_empty_method_call_parentheses = false
+ij_groovy_spaces_around_additive_operators = true
+ij_groovy_spaces_around_assignment_operators = true
+ij_groovy_spaces_around_bitwise_operators = true
+ij_groovy_spaces_around_equality_operators = true
+ij_groovy_spaces_around_lambda_arrow = true
+ij_groovy_spaces_around_logical_operators = true
+ij_groovy_spaces_around_multiplicative_operators = true
+ij_groovy_spaces_around_relational_operators = true
+ij_groovy_spaces_around_shift_operators = true
+ij_groovy_spaces_within_annotation_parentheses = false
+ij_groovy_spaces_within_array_initializer_braces = false
+ij_groovy_spaces_within_braces = true
+ij_groovy_spaces_within_brackets = false
+ij_groovy_spaces_within_cast_parentheses = false
+ij_groovy_spaces_within_catch_parentheses = false
+ij_groovy_spaces_within_for_parentheses = false
+ij_groovy_spaces_within_if_parentheses = false
+ij_groovy_spaces_within_method_call_parentheses = false
+ij_groovy_spaces_within_method_parentheses = false
+ij_groovy_spaces_within_parentheses = false
+ij_groovy_spaces_within_switch_parentheses = false
+ij_groovy_spaces_within_synchronized_parentheses = false
+ij_groovy_spaces_within_try_parentheses = false
+ij_groovy_spaces_within_while_parentheses = false
+ij_groovy_special_else_if_treatment = true
+ij_groovy_ternary_operation_wrap = off
+ij_groovy_throws_keyword_wrap = off
+ij_groovy_throws_list_wrap = off
+ij_groovy_use_relative_indents = false
+ij_groovy_variable_annotation_wrap = off
+ij_groovy_while_brace_force = never
+ij_groovy_while_on_new_line = false
+ij_groovy_wrap_long_lines = false
+
+[{*.jhm,*.xjb,*.rng,*.wsdl,*.wsdd,*.fxml,*.plan,*.bpmn,*.pom,*.xslt,*.jrxml,*.ant,*.xul,*.xsl,*.xsd,*.tld,*.jnlp,*.wadl,*.xml}]
+ij_xml_block_comment_at_first_column = true
+ij_xml_keep_indents_on_empty_lines = false
+ij_xml_line_comment_at_first_column = true
+ij_xml_use_custom_settings = false
+
+[{*.jspx,*.tagx}]
+ij_jspx_keep_indents_on_empty_lines = false
+
+[{*.kts,*.kt}]
+ij_kotlin_align_in_columns_case_branch = false
+ij_kotlin_align_multiline_binary_operation = false
+ij_kotlin_align_multiline_extends_list = false
+ij_kotlin_align_multiline_method_parentheses = false
+ij_kotlin_align_multiline_parameters = true
+ij_kotlin_align_multiline_parameters_in_calls = false
+ij_kotlin_assignment_wrap = off
+ij_kotlin_blank_lines_after_class_header = 0
+ij_kotlin_blank_lines_around_block_when_branches = 0
+ij_kotlin_block_comment_at_first_column = true
+ij_kotlin_call_parameters_new_line_after_left_paren = false
+ij_kotlin_call_parameters_right_paren_on_new_line = false
+ij_kotlin_call_parameters_wrap = off
+ij_kotlin_catch_on_new_line = false
+ij_kotlin_class_annotation_wrap = split_into_lines
+ij_kotlin_continuation_indent_for_chained_calls = true
+ij_kotlin_continuation_indent_for_expression_bodies = true
+ij_kotlin_continuation_indent_in_argument_lists = true
+ij_kotlin_continuation_indent_in_elvis = true
+ij_kotlin_continuation_indent_in_if_conditions = true
+ij_kotlin_continuation_indent_in_parameter_lists = true
+ij_kotlin_continuation_indent_in_supertype_lists = true
+ij_kotlin_else_on_new_line = false
+ij_kotlin_enum_constants_wrap = off
+ij_kotlin_extends_list_wrap = off
+ij_kotlin_field_annotation_wrap = split_into_lines
+ij_kotlin_finally_on_new_line = false
+ij_kotlin_if_rparen_on_new_line = false
+ij_kotlin_import_nested_classes = false
+ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
+ij_kotlin_keep_blank_lines_before_right_brace = 2
+ij_kotlin_keep_blank_lines_in_code = 2
+ij_kotlin_keep_blank_lines_in_declarations = 2
+ij_kotlin_keep_first_column_comment = true
+ij_kotlin_keep_indents_on_empty_lines = false
+ij_kotlin_keep_line_breaks = true
+ij_kotlin_lbrace_on_next_line = false
+ij_kotlin_line_comment_add_space = false
+ij_kotlin_line_comment_at_first_column = true
+ij_kotlin_method_annotation_wrap = split_into_lines
+ij_kotlin_method_call_chain_wrap = off
+ij_kotlin_method_parameters_new_line_after_left_paren = false
+ij_kotlin_method_parameters_right_paren_on_new_line = false
+ij_kotlin_method_parameters_wrap = off
+ij_kotlin_name_count_to_use_star_import = 5
+ij_kotlin_name_count_to_use_star_import_for_members = 3
+ij_kotlin_parameter_annotation_wrap = off
+ij_kotlin_space_after_comma = true
+ij_kotlin_space_after_extend_colon = true
+ij_kotlin_space_after_type_colon = true
+ij_kotlin_space_before_catch_parentheses = true
+ij_kotlin_space_before_comma = false
+ij_kotlin_space_before_extend_colon = true
+ij_kotlin_space_before_for_parentheses = true
+ij_kotlin_space_before_if_parentheses = true
+ij_kotlin_space_before_lambda_arrow = true
+ij_kotlin_space_before_type_colon = false
+ij_kotlin_space_before_when_parentheses = true
+ij_kotlin_space_before_while_parentheses = true
+ij_kotlin_spaces_around_additive_operators = true
+ij_kotlin_spaces_around_assignment_operators = true
+ij_kotlin_spaces_around_equality_operators = true
+ij_kotlin_spaces_around_function_type_arrow = true
+ij_kotlin_spaces_around_logical_operators = true
+ij_kotlin_spaces_around_multiplicative_operators = true
+ij_kotlin_spaces_around_range = false
+ij_kotlin_spaces_around_relational_operators = true
+ij_kotlin_spaces_around_unary_operator = false
+ij_kotlin_spaces_around_when_arrow = true
+ij_kotlin_variable_annotation_wrap = off
+ij_kotlin_while_on_new_line = false
+ij_kotlin_wrap_elvis_expressions = 1
+ij_kotlin_wrap_expression_body_functions = 0
+ij_kotlin_wrap_first_method_in_call_chain = false
+
+[{*.sht,*.htm,*.html,*.shtm,*.shtml,*.ng}]
+ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
+ij_html_align_attributes = true
+ij_html_align_text = false
+ij_html_attribute_wrap = normal
+ij_html_block_comment_at_first_column = true
+ij_html_do_not_align_children_of_min_lines = 0
+ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
+ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
+ij_html_enforce_quotes = false
+ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
+ij_html_keep_blank_lines = 2
+ij_html_keep_indents_on_empty_lines = false
+ij_html_keep_line_breaks = true
+ij_html_keep_line_breaks_in_text = true
+ij_html_keep_whitespaces = false
+ij_html_keep_whitespaces_inside = span,pre,textarea
+ij_html_line_comment_at_first_column = true
+ij_html_new_line_after_last_attribute = never
+ij_html_new_line_before_first_attribute = never
+ij_html_quote_style = double
+ij_html_remove_new_line_before_tags = br
+ij_html_space_after_tag_name = false
+ij_html_space_around_equality_in_attribute = false
+ij_html_space_inside_empty_tag = false
+ij_html_text_wrap = normal
+
+[{*.ts,*.ats}]
+ij_continuation_indent_size = 4
+ij_typescript_align_imports = false
+ij_typescript_align_multiline_array_initializer_expression = false
+ij_typescript_align_multiline_binary_operation = false
+ij_typescript_align_multiline_chained_methods = false
+ij_typescript_align_multiline_extends_list = false
+ij_typescript_align_multiline_for = true
+ij_typescript_align_multiline_parameters = true
+ij_typescript_align_multiline_parameters_in_calls = false
+ij_typescript_align_multiline_ternary_operation = false
+ij_typescript_align_object_properties = 0
+ij_typescript_align_union_types = false
+ij_typescript_align_var_statements = 0
+ij_typescript_array_initializer_new_line_after_left_brace = false
+ij_typescript_array_initializer_right_brace_on_new_line = false
+ij_typescript_array_initializer_wrap = off
+ij_typescript_assignment_wrap = off
+ij_typescript_binary_operation_sign_on_next_line = false
+ij_typescript_binary_operation_wrap = off
+ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**/*,@angular/material,@angular/material/typings/**,~/node_modules/**/*,@/node_modules/**/*
+ij_typescript_blank_lines_after_imports = 1
+ij_typescript_blank_lines_around_class = 1
+ij_typescript_blank_lines_around_field = 0
+ij_typescript_blank_lines_around_field_in_interface = 0
+ij_typescript_blank_lines_around_function = 1
+ij_typescript_blank_lines_around_method = 1
+ij_typescript_blank_lines_around_method_in_interface = 1
+ij_typescript_block_brace_style = end_of_line
+ij_typescript_call_parameters_new_line_after_left_paren = false
+ij_typescript_call_parameters_right_paren_on_new_line = false
+ij_typescript_call_parameters_wrap = off
+ij_typescript_catch_on_new_line = false
+ij_typescript_chained_call_dot_on_new_line = true
+ij_typescript_class_brace_style = end_of_line
+ij_typescript_comma_on_new_line = false
+ij_typescript_do_while_brace_force = never
+ij_typescript_else_on_new_line = false
+ij_typescript_enforce_trailing_comma = keep
+ij_typescript_extends_keyword_wrap = off
+ij_typescript_extends_list_wrap = off
+ij_typescript_field_prefix = _
+ij_typescript_file_name_style = relaxed
+ij_typescript_finally_on_new_line = false
+ij_typescript_for_brace_force = never
+ij_typescript_for_statement_new_line_after_left_paren = false
+ij_typescript_for_statement_right_paren_on_new_line = false
+ij_typescript_for_statement_wrap = off
+ij_typescript_force_quote_style = false
+ij_typescript_force_semicolon_style = false
+ij_typescript_function_expression_brace_style = end_of_line
+ij_typescript_if_brace_force = never
+ij_typescript_import_merge_members = global
+ij_typescript_import_prefer_absolute_path = global
+ij_typescript_import_sort_members = true
+ij_typescript_import_sort_module_name = false
+ij_typescript_import_use_node_resolution = true
+ij_typescript_imports_wrap = on_every_item
+ij_typescript_indent_case_from_switch = true
+ij_typescript_indent_chained_calls = true
+ij_typescript_indent_package_children = 0
+ij_typescript_jsdoc_include_types = false
+ij_typescript_jsx_attribute_value = braces
+ij_typescript_keep_blank_lines_in_code = 2
+ij_typescript_keep_first_column_comment = true
+ij_typescript_keep_indents_on_empty_lines = false
+ij_typescript_keep_line_breaks = true
+ij_typescript_keep_simple_blocks_in_one_line = false
+ij_typescript_keep_simple_methods_in_one_line = false
+ij_typescript_line_comment_add_space = true
+ij_typescript_line_comment_at_first_column = false
+ij_typescript_method_brace_style = end_of_line
+ij_typescript_method_call_chain_wrap = off
+ij_typescript_method_parameters_new_line_after_left_paren = false
+ij_typescript_method_parameters_right_paren_on_new_line = false
+ij_typescript_method_parameters_wrap = off
+ij_typescript_object_literal_wrap = on_every_item
+ij_typescript_parentheses_expression_new_line_after_left_paren = false
+ij_typescript_parentheses_expression_right_paren_on_new_line = false
+ij_typescript_place_assignment_sign_on_next_line = false
+ij_typescript_prefer_as_type_cast = false
+ij_typescript_prefer_parameters_wrap = false
+ij_typescript_reformat_c_style_comments = false
+ij_typescript_space_after_colon = true
+ij_typescript_space_after_comma = true
+ij_typescript_space_after_dots_in_rest_parameter = false
+ij_typescript_space_after_generator_mult = true
+ij_typescript_space_after_property_colon = true
+ij_typescript_space_after_quest = true
+ij_typescript_space_after_type_colon = true
+ij_typescript_space_after_unary_not = false
+ij_typescript_space_before_async_arrow_lparen = true
+ij_typescript_space_before_catch_keyword = true
+ij_typescript_space_before_catch_left_brace = true
+ij_typescript_space_before_catch_parentheses = true
+ij_typescript_space_before_class_lbrace = true
+ij_typescript_space_before_class_left_brace = true
+ij_typescript_space_before_colon = true
+ij_typescript_space_before_comma = false
+ij_typescript_space_before_do_left_brace = true
+ij_typescript_space_before_else_keyword = true
+ij_typescript_space_before_else_left_brace = true
+ij_typescript_space_before_finally_keyword = true
+ij_typescript_space_before_finally_left_brace = true
+ij_typescript_space_before_for_left_brace = true
+ij_typescript_space_before_for_parentheses = true
+ij_typescript_space_before_for_semicolon = false
+ij_typescript_space_before_function_left_parenth = true
+ij_typescript_space_before_generator_mult = false
+ij_typescript_space_before_if_left_brace = true
+ij_typescript_space_before_if_parentheses = true
+ij_typescript_space_before_method_call_parentheses = false
+ij_typescript_space_before_method_left_brace = true
+ij_typescript_space_before_method_parentheses = false
+ij_typescript_space_before_property_colon = false
+ij_typescript_space_before_quest = true
+ij_typescript_space_before_switch_left_brace = true
+ij_typescript_space_before_switch_parentheses = true
+ij_typescript_space_before_try_left_brace = true
+ij_typescript_space_before_type_colon = false
+ij_typescript_space_before_unary_not = false
+ij_typescript_space_before_while_keyword = true
+ij_typescript_space_before_while_left_brace = true
+ij_typescript_space_before_while_parentheses = true
+ij_typescript_spaces_around_additive_operators = true
+ij_typescript_spaces_around_arrow_function_operator = true
+ij_typescript_spaces_around_assignment_operators = true
+ij_typescript_spaces_around_bitwise_operators = true
+ij_typescript_spaces_around_equality_operators = true
+ij_typescript_spaces_around_logical_operators = true
+ij_typescript_spaces_around_multiplicative_operators = true
+ij_typescript_spaces_around_relational_operators = true
+ij_typescript_spaces_around_shift_operators = true
+ij_typescript_spaces_around_unary_operator = false
+ij_typescript_spaces_within_array_initializer_brackets = false
+ij_typescript_spaces_within_brackets = false
+ij_typescript_spaces_within_catch_parentheses = false
+ij_typescript_spaces_within_for_parentheses = false
+ij_typescript_spaces_within_if_parentheses = false
+ij_typescript_spaces_within_imports = false
+ij_typescript_spaces_within_interpolation_expressions = false
+ij_typescript_spaces_within_method_call_parentheses = false
+ij_typescript_spaces_within_method_parentheses = false
+ij_typescript_spaces_within_object_literal_braces = false
+ij_typescript_spaces_within_object_type_braces = true
+ij_typescript_spaces_within_parentheses = false
+ij_typescript_spaces_within_switch_parentheses = false
+ij_typescript_spaces_within_type_assertion = false
+ij_typescript_spaces_within_union_types = true
+ij_typescript_spaces_within_while_parentheses = false
+ij_typescript_special_else_if_treatment = true
+ij_typescript_ternary_operation_signs_on_next_line = false
+ij_typescript_ternary_operation_wrap = off
+ij_typescript_union_types_wrap = on_every_item
+ij_typescript_use_chained_calls_group_indents = false
+ij_typescript_use_double_quotes = true
+ij_typescript_use_explicit_js_extension = global
+ij_typescript_use_path_mapping = always
+ij_typescript_use_public_modifier = false
+ij_typescript_use_semicolon_after_statement = true
+ij_typescript_var_declaration_wrap = normal
+ij_typescript_while_brace_force = never
+ij_typescript_while_on_new_line = false
+ij_typescript_wrap_comments = false
+
+[{*.vsl,*.vm,*.ft}]
+ij_vtl_keep_indents_on_empty_lines = false
+
+[{*.xjsp,*.tag,*.jsp,*.jsf,*.jspf,*.tagf}]
+ij_jsp_jsp_prefer_comma_separated_import_list = false
+ij_jsp_keep_indents_on_empty_lines = false
+
+[{*.yml,*.yaml}]
+indent_size = 2
+ij_yaml_keep_indents_on_empty_lines = false
+ij_yaml_keep_line_breaks = true
+
+[{*.zsh,*.bash,*.sh}]
+indent_size = 2
+tab_width = 2
+ij_shell_binary_ops_start_line = false
+ij_shell_keep_column_alignment_padding = false
+ij_shell_minify_program = false
+ij_shell_redirect_followed_by_space = false
+ij_shell_switch_cases_indented = false
+
+[{.babelrc,.stylelintrc,.eslintrc,jest.config,bowerrc,*.jsb3,*.jsb2,*.json}]
+indent_size = 2
+ij_json_keep_blank_lines_in_code = 0
+ij_json_keep_indents_on_empty_lines = false
+ij_json_keep_line_breaks = true
+ij_json_space_after_colon = true
+ij_json_space_after_comma = true
+ij_json_space_before_colon = true
+ij_json_space_before_comma = false
+ij_json_spaces_within_braces = false
+ij_json_spaces_within_brackets = false
+ij_json_wrap_long_lines = false
+
+[{spring.schemas,spring.handlers,*.properties}]
+ij_properties_align_group_field_declarations = false
diff --git a/.gitattributes b/.gitattributes
index d72fd520b1c..8fc1e12adae 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,106 @@
+# These settings are for any web project
+
+# Handle line endings automatically for files detected as text
+# and leave all files detected as binary untouched.
+# * text=auto
+# NOTE - originally I had the above line un-commented. it caused me a lot of grief related to line endings because I was dealing with WordPress plugins and the website changing line endings out if a user modified a plugin through the web interface. commenting this line out seems to have alleviated the git chaos where simply switching to a branch caused it to believe 500 files were modified.
+
+#
+# The above will handle all files NOT found below
+#
+
+#
+## These files are text and should be normalized (Convert crlf => lf)
+#
+# source code
+*.php text
+*.css text
+*.sass text
+*.scss text
+*.less text
+*.styl text
+*.js text
+*.coffee text
+*.json text
+*.htm text
+*.html text
+*.xml text
+*.svg text
+*.txt text
+*.ini text
+*.inc text
+*.pl text
+*.rb text
+*.py text
+*.scm text
+*.sql text
+*.sh text
+*.bat text
+
+# templates
+*.ejs text
+*.hbt text
+*.jade text
+*.haml text
+*.hbs text
+*.dot text
+*.tmpl text
+*.phtml text
+
+# server config
+.htaccess text
+
+# git config
+.gitattributes text
+.gitignore text
+.gitconfig text
+
+# code analysis config
+.jshintrc text
+.jscsrc text
+.jshintignore text
+.csslintrc text
+
+# misc config
+*.yaml text
+*.yml text
+.editorconfig text
+
+# build config
+*.npmignore text
+*.bowerrc text
+
+# Heroku
+Procfile text
+.slugignore text
+
+# Documentation
+*.md text
+LICENSE text
+AUTHORS text
+
+
+#
+## These files are binary and should be left untouched
+#
+
+# (binary is a macro for -text -diff)
+*.png binary
+*.jpg binary
+*.jpeg binary
+*.gif binary
+*.ico binary
+*.mov binary
+*.mp4 binary
+*.mp3 binary
+*.flv binary
+*.fla binary
+*.swf binary
+*.gz binary
+*.zip binary
+*.7z binary
+*.ttf binary
+*.eot binary
+*.woff binary
+*.pyc binary
*.pdf binary
diff --git a/.gitignore b/.gitignore
index 5e59b862ba4..a020b449faf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,6 @@ src/test/data/sandbox/
# MacOS custom attributes files created by Finder
.DS_Store
+
+#dian hao uml file
+docs/yapdianhaoUML.adoc
diff --git a/.project b/.project
new file mode 100644
index 00000000000..f151561e3e9
--- /dev/null
+++ b/.project
@@ -0,0 +1,23 @@
+
+
+ main
+ Project main created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..e8895216fd3
--- /dev/null
+++ b/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=
+eclipse.preferences.version=1
diff --git a/README.adoc b/README.adoc
index e36efe534bb..2fb43217ecc 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,29 +1,25 @@
-= Address Book (Level 3)
+= JelphaBot - Personalised Task Manager
ifdef::env-github,env-browser[:relfileprefix: docs/]
-https://travis-ci.org/se-edu/addressbook-level3[image:https://travis-ci.org/se-edu/addressbook-level3.svg?branch=master[Build Status]]
-https://ci.appveyor.com/project/damithc/addressbook-level3[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]]
-https://coveralls.io/github/se-edu/addressbook-level3?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level3/badge.svg?branch=master[Coverage Status]]
-https://www.codacy.com/app/damith/addressbook-level3?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level3&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]]
-
+https://travis-ci.org/AY1920S2-CS2103T-F09-2/main[image:https://travis-ci.org/se-edu/addressbook-level3.svg?branch=master[Build Status]]
+https://ci.appveyor.com/project/Clouddoggo/main/branch/master[image:https://ci.appveyor.com/api/projects/status/3vmwqwd4y4fc4ini/branch/master?svg=true[Build status]]
+https://coveralls.io/github/AY1920S2-CS2103T-F09-2/main?branch=master[image:https://coveralls.io/repos/github/AY1920S2-CS2103T-F09-2/main/badge.svg?branch=master[Coverage Status]]
ifdef::env-github[]
-image::docs/images/Ui.png[width="600"]
+image::docs/images/ug_figures/Ui.png[width="600"]
endif::[]
ifndef::env-github[]
-image::images/Ui.png[width="600"]
+image::docs/images/ug_figures/Ui.png[width="600"]
endif::[]
-* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface).
-* It is a Java sample application intended for students learning Software Engineering while using Java as the main programming language.
-* It is *written in OOP fashion*. It provides a *reasonably well-written* code example that is *significantly bigger* (around 6 KLoC)than what students usually write in beginner-level SE modules.
+* JelphaBot is your very own personal Task Manager to help University Students keep track of their modules and various assignments and commitments.
+* It is a desktop Task Manager application. It has a GUI but most of the user interactions occur through the CLI (Command Line Interface).
== Site Map
* <>
* <>
-* <>
* <>
* <>
@@ -32,5 +28,7 @@ endif::[]
* Some parts of this sample application were inspired by the excellent http://code.makery.ch/library/javafx-8-tutorial/[Java FX tutorial] by
_Marco Jakob_.
* Libraries used: https://openjfx.io/[JavaFX], https://github.com/FasterXML/jackson[Jackson], https://github.com/junit-team/junit5[JUnit5]
+* JelphaBot is based on the AddressBook-Level3 project created by SE-EDU initiative at https://se-education.org
+* Icons used: https://www.freepik.com/[JelphaBot icon], https://www.pinclipart.com/pindetail/iioRTiJ_alarm-clock-comments-medication-reminders-icon-png-clipart/[Reminder popup icon]
== Licence : link:LICENSE[MIT]
diff --git a/_reposense/config.json b/_reposense/config.json
new file mode 100644
index 00000000000..a45fed00543
--- /dev/null
+++ b/_reposense/config.json
@@ -0,0 +1,38 @@
+{
+ "ignoreCommitList": [
+ "493206f16e1593adef8904bcb521aa4e4b2bf36e",
+ "aae9da92cff0db4e37ed8de0c30ffb2b2c8541e6",
+ "d0cbc3106d15f960417f9e80f9a1c7a9acd90441",
+ "4ff825e4a8004ec9bcf9727287ae687266e74b47",
+ "029c16c644df0a81e9c29f74dc856f9a5c206bf2",
+ "d0cbc3106d15f960417f9e80f9a1c7a9acd90441"
+ ],
+ "authors":
+ [
+ {
+ "githubId": "alam8064",
+ "displayName": "AMA. . .ING",
+ "authorNames": ["alam8064", "Amanda Lam"]
+ },
+ {
+ "githubId": "Clouddoggo",
+ "displayName": "LIM. . .JEL",
+ "authorNames": ["Clouddoggo", "Jel Lim"]
+ },
+ {
+ "githubId": "eedenong",
+ "displayName": "ONG. . .DEN",
+ "authorNames": ["eedenong", "Eden Ong"]
+ },
+ {
+ "githubId": "yaojiethng",
+ "displayName": "THN. . .JIE",
+ "authorNames": ["yaojiethng", "Thng Yao Jie"]
+ },
+ {
+ "githubId": "yapdianhao",
+ "displayName": "YAP. . .HAO",
+ "authorNames": ["yapdianhao", "Yap Dian Hao"]
+ }
+ ]
+}
diff --git a/bin/main/images/address_book_32.png b/bin/main/images/address_book_32.png
new file mode 100644
index 00000000000..8f8f90d7c4d
Binary files /dev/null and b/bin/main/images/address_book_32.png differ
diff --git a/bin/main/images/calendar.png b/bin/main/images/calendar.png
new file mode 100644
index 00000000000..7c880e61628
Binary files /dev/null and b/bin/main/images/calendar.png differ
diff --git a/bin/main/images/clock.png b/bin/main/images/clock.png
new file mode 100644
index 00000000000..7144ed1b065
Binary files /dev/null and b/bin/main/images/clock.png differ
diff --git a/bin/main/images/fail.png b/bin/main/images/fail.png
new file mode 100644
index 00000000000..8edc2a69860
Binary files /dev/null and b/bin/main/images/fail.png differ
diff --git a/bin/main/images/help_icon.png b/bin/main/images/help_icon.png
new file mode 100644
index 00000000000..d3c7a76fc49
Binary files /dev/null and b/bin/main/images/help_icon.png differ
diff --git a/bin/main/images/info_icon.png b/bin/main/images/info_icon.png
new file mode 100644
index 00000000000..b806d236453
Binary files /dev/null and b/bin/main/images/info_icon.png differ
diff --git a/bin/main/view/CommandBox.fxml b/bin/main/view/CommandBox.fxml
new file mode 100644
index 00000000000..09f6d6fe9e4
--- /dev/null
+++ b/bin/main/view/CommandBox.fxml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/bin/main/view/DarkTheme.css b/bin/main/view/DarkTheme.css
new file mode 100644
index 00000000000..19e9da885ce
--- /dev/null
+++ b/bin/main/view/DarkTheme.css
@@ -0,0 +1,353 @@
+.background {
+ -fx-background-color: derive(#1d1d1d, 20%);
+ background-color: #383838; /* Used in the default.html file */
+}
+
+.label {
+ -fx-font-size: 11pt;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-text-fill: #555555;
+ -fx-opacity: 0.9;
+}
+
+.label-bright {
+ -fx-font-size: 11pt;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-text-fill: white;
+ -fx-opacity: 1;
+}
+
+.label-header {
+ -fx-font-size: 32pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-opacity: 1;
+}
+
+.text-field {
+ -fx-font-size: 12pt;
+ -fx-font-family: "Segoe UI Semibold";
+}
+
+.tab-pane {
+ -fx-padding: 0 0 0 1;
+}
+
+.tab-pane .tab-header-area {
+ -fx-padding: 0 0 0 0;
+ -fx-min-height: 0;
+ -fx-max-height: 0;
+}
+
+.table-view {
+ -fx-base: #1d1d1d;
+ -fx-control-inner-background: #1d1d1d;
+ -fx-background-color: #1d1d1d;
+ -fx-table-cell-border-color: transparent;
+ -fx-table-header-border-color: transparent;
+ -fx-padding: 5;
+}
+
+.table-view .column-header-background {
+ -fx-background-color: transparent;
+}
+
+.table-view .column-header, .table-view .filler {
+ -fx-size: 35px;
+ -fx-border-width: 0 0 1 0;
+ -fx-background-color: transparent;
+ -fx-border-color:
+ transparent
+ transparent
+ derive(-fx-base, 80%)
+ transparent;
+ -fx-border-insets: 0 10 1 0;
+}
+
+.table-view .column-header .label {
+ -fx-font-size: 20pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-alignment: center-left;
+ -fx-opacity: 1;
+}
+
+.table-view:focused .table-row-cell:filled:focused:selected {
+ -fx-background-color: -fx-focus-color;
+}
+
+.split-pane:horizontal .split-pane-divider {
+ -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-border-color: transparent transparent transparent #4d4d4d;
+}
+
+.split-pane {
+ -fx-border-radius: 1;
+ -fx-border-width: 1;
+ -fx-background-color: derive(#1d1d1d, 20%);
+}
+
+.list-view {
+ -fx-background-insets: 0;
+ -fx-padding: 0;
+ -fx-background-color: derive(#1d1d1d, 20%);
+}
+
+.list-cell {
+ -fx-label-padding: 0 0 0 0;
+ -fx-graphic-text-gap: 0;
+ -fx-padding: 0 0 0 0;
+ -fx-pref-height: 105;
+}
+
+.list-cell:filled:even {
+ -fx-background-color: #3c3e3f;
+}
+
+.list-cell:filled:odd {
+ -fx-background-color: #515658;
+}
+
+.list-cell:filled:selected {
+ -fx-background-color: #424d5f;
+}
+
+.list-cell:filled:selected #cardPane {
+ -fx-border-color: #3e7b91;
+ -fx-border-width: 1;
+}
+
+.list-cell .label {
+ -fx-text-fill: white;
+}
+
+.cell_big_label {
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 16px;
+ -fx-text-fill: #010504;
+}
+
+.cell_small_label {
+ -fx-font-family: "Segoe UI";
+ -fx-font-size: 13px;
+ -fx-text-fill: #010504;
+}
+
+.stack-pane {
+ -fx-background-color: derive(#1d1d1d, 20%);
+}
+
+.pane-with-border {
+ -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-border-color: derive(#1d1d1d, 10%);
+ -fx-border-top-width: 1px;
+}
+
+.status-bar {
+ -fx-background-color: derive(#1d1d1d, 30%);
+}
+
+.result-display {
+ -fx-background-color: transparent;
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: white;
+}
+
+.result-display .label {
+ -fx-text-fill: black !important;
+}
+
+.status-bar .label {
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-padding: 4px;
+ -fx-pref-height: 30px;
+}
+
+.status-bar-with-border {
+ -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-border-color: derive(#1d1d1d, 25%);
+ -fx-border-width: 1px;
+}
+
+.status-bar-with-border .label {
+ -fx-text-fill: white;
+}
+
+.grid-pane {
+ -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-border-color: derive(#1d1d1d, 30%);
+ -fx-border-width: 1px;
+}
+
+.grid-pane .stack-pane {
+ -fx-background-color: derive(#1d1d1d, 30%);
+}
+
+.context-menu {
+ -fx-background-color: derive(#1d1d1d, 50%);
+}
+
+.context-menu .label {
+ -fx-text-fill: white;
+}
+
+.menu-bar {
+ -fx-background-color: derive(#1d1d1d, 20%);
+}
+
+.menu-bar .label {
+ -fx-font-size: 14pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-opacity: 0.9;
+}
+
+.menu .left-container {
+ -fx-background-color: black;
+}
+
+/*
+ * Metro style Push Button
+ * Author: Pedro Duque Vieira
+ * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
+ */
+.button {
+ -fx-padding: 5 22 5 22;
+ -fx-border-color: #e2e2e2;
+ -fx-border-width: 2;
+ -fx-background-radius: 0;
+ -fx-background-color: #1d1d1d;
+ -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+ -fx-font-size: 11pt;
+ -fx-text-fill: #d8d8d8;
+ -fx-background-insets: 0 0 0 0, 0, 1, 2;
+}
+
+.button:hover {
+ -fx-background-color: #3a3a3a;
+}
+
+.button:pressed, .button:default:hover:pressed {
+ -fx-background-color: white;
+ -fx-text-fill: #1d1d1d;
+}
+
+.button:focused {
+ -fx-border-color: white, white;
+ -fx-border-width: 1, 1;
+ -fx-border-style: solid, segments(1, 1);
+ -fx-border-radius: 0, 0;
+ -fx-border-insets: 1 1 1 1, 0;
+}
+
+.button:disabled, .button:default:disabled {
+ -fx-opacity: 0.4;
+ -fx-background-color: #1d1d1d;
+ -fx-text-fill: white;
+}
+
+.button:default {
+ -fx-background-color: -fx-focus-color;
+ -fx-text-fill: #ffffff;
+}
+
+.button:default:hover {
+ -fx-background-color: derive(-fx-focus-color, 30%);
+}
+
+.dialog-pane {
+ -fx-background-color: #1d1d1d;
+}
+
+.dialog-pane > *.button-bar > *.container {
+ -fx-background-color: #1d1d1d;
+}
+
+.dialog-pane > *.label.content {
+ -fx-font-size: 14px;
+ -fx-font-weight: bold;
+ -fx-text-fill: white;
+}
+
+.dialog-pane:header *.header-panel {
+ -fx-background-color: derive(#1d1d1d, 25%);
+}
+
+.dialog-pane:header *.header-panel *.label {
+ -fx-font-size: 18px;
+ -fx-font-style: italic;
+ -fx-fill: white;
+ -fx-text-fill: white;
+}
+
+.scroll-bar {
+ -fx-background-color: derive(#1d1d1d, 20%);
+}
+
+.scroll-bar .thumb {
+ -fx-background-color: derive(#1d1d1d, 50%);
+ -fx-background-insets: 3;
+}
+
+.scroll-bar .increment-button, .scroll-bar .decrement-button {
+ -fx-background-color: transparent;
+ -fx-padding: 0 0 0 0;
+}
+
+.scroll-bar .increment-arrow, .scroll-bar .decrement-arrow {
+ -fx-shape: " ";
+}
+
+.scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow {
+ -fx-padding: 1 8 1 8;
+}
+
+.scroll-bar:horizontal .increment-arrow, .scroll-bar:horizontal .decrement-arrow {
+ -fx-padding: 8 1 8 1;
+}
+
+#cardPane {
+ -fx-background-color: transparent;
+ -fx-border-width: 0;
+}
+
+#commandTypeLabel {
+ -fx-font-size: 11px;
+ -fx-text-fill: #F70D1A;
+}
+
+#commandTextField {
+ -fx-background-color: transparent #383838 transparent #383838;
+ -fx-background-insets: 0;
+ -fx-border-color: #383838 #383838 #ffffff #383838;
+ -fx-border-insets: 0;
+ -fx-border-width: 1;
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: white;
+}
+
+#filterField, #personListPanel, #personWebpage {
+ -fx-effect: innershadow(gaussian, black, 10, 0, 0, 0);
+}
+
+#resultDisplay .content {
+ -fx-background-color: transparent, #383838, transparent, #383838;
+ -fx-background-radius: 0;
+}
+
+#tags {
+ -fx-hgap: 7;
+ -fx-vgap: 3;
+}
+
+#tags .label {
+ -fx-text-fill: white;
+ -fx-background-color: #3e7b91;
+ -fx-padding: 1 3 1 3;
+ -fx-border-radius: 2;
+ -fx-background-radius: 2;
+ -fx-font-size: 11;
+}
diff --git a/bin/main/view/Extensions.css b/bin/main/view/Extensions.css
new file mode 100644
index 00000000000..bfe82a85964
--- /dev/null
+++ b/bin/main/view/Extensions.css
@@ -0,0 +1,20 @@
+
+.error {
+ -fx-text-fill: #d06651 !important; /* The error class should always override the default text-fill style */
+}
+
+.list-cell:empty {
+ /* Empty cells will not have alternating colours */
+ -fx-background: #383838;
+}
+
+.tag-selector {
+ -fx-border-width: 1;
+ -fx-border-color: white;
+ -fx-border-radius: 3;
+ -fx-background-radius: 3;
+}
+
+.tooltip-text {
+ -fx-text-fill: white;
+}
diff --git a/bin/main/view/HelpWindow.fxml b/bin/main/view/HelpWindow.fxml
new file mode 100644
index 00000000000..fa0fb54d9f4
--- /dev/null
+++ b/bin/main/view/HelpWindow.fxml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bin/main/view/MainWindow.fxml b/bin/main/view/MainWindow.fxml
new file mode 100644
index 00000000000..0e2a832c2e2
--- /dev/null
+++ b/bin/main/view/MainWindow.fxml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/PersonListCard.fxml b/bin/main/view/PersonListCard.fxml
similarity index 100%
rename from src/main/resources/view/PersonListCard.fxml
rename to bin/main/view/PersonListCard.fxml
diff --git a/src/main/resources/view/PersonListPanel.fxml b/bin/main/view/PersonListPanel.fxml
similarity index 100%
rename from src/main/resources/view/PersonListPanel.fxml
rename to bin/main/view/PersonListPanel.fxml
diff --git a/bin/main/view/ResultDisplay.fxml b/bin/main/view/ResultDisplay.fxml
new file mode 100644
index 00000000000..f5f47011004
--- /dev/null
+++ b/bin/main/view/ResultDisplay.fxml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/bin/main/view/StatusBarFooter.fxml b/bin/main/view/StatusBarFooter.fxml
new file mode 100644
index 00000000000..149f62bd29c
--- /dev/null
+++ b/bin/main/view/StatusBarFooter.fxml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bin/test/view/UiPartTest/invalidFile.fxml b/bin/test/view/UiPartTest/invalidFile.fxml
new file mode 100644
index 00000000000..67680946732
--- /dev/null
+++ b/bin/test/view/UiPartTest/invalidFile.fxml
@@ -0,0 +1 @@
+Not a valid FXML file
diff --git a/bin/test/view/UiPartTest/validFile.fxml b/bin/test/view/UiPartTest/validFile.fxml
new file mode 100644
index 00000000000..bab836af0db
--- /dev/null
+++ b/bin/test/view/UiPartTest/validFile.fxml
@@ -0,0 +1,4 @@
+
+
+
+Hello World!
diff --git a/bin/test/view/UiPartTest/validFileWithFxRoot.fxml b/bin/test/view/UiPartTest/validFileWithFxRoot.fxml
new file mode 100644
index 00000000000..151e09ce926
--- /dev/null
+++ b/bin/test/view/UiPartTest/validFileWithFxRoot.fxml
@@ -0,0 +1,6 @@
+
+
+
+ Hello World!
+
diff --git a/build.gradle b/build.gradle
index 93029ef8262..52e68638a5e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,13 +9,13 @@ plugins {
id 'jacoco'
id 'checkstyle'
id 'com.github.kt3k.coveralls' version '2.4.0'
- id 'com.github.johnrengelman.shadow' version '4.0.4'
+ id 'com.github.johnrengelman.shadow' version '5.1.0'
id 'org.asciidoctor.convert' version '1.5.6'
id 'application'
}
// Specifies the entry point of the application
-mainClassName = 'seedu.address.Main'
+mainClassName = 'seedu.jelphabot.Main'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
@@ -67,7 +67,7 @@ dependencies {
}
shadowJar {
- archiveName = 'addressbook.jar'
+ archiveName = 'jelphaBot.jar'
destinationDir = file("${buildDir}/jar/")
}
@@ -133,9 +133,8 @@ asciidoctor {
idprefix: '', // for compatibility with GitHub preview
idseparator: '-',
'site-root': "${sourceDir}", // must be the same as sourceDir, do not modify
- 'site-name': 'AddressBook-Level3',
- 'site-githuburl': 'https://github.com/se-edu/addressbook-level3',
- 'site-seedu': true, // delete this line if your project is not a fork (not a SE-EDU project)
+ 'site-name': 'JelphaBot',
+ 'site-githuburl': 'https://github.com/AY1920S2-CS2103T-F09-2/main'
]
options['template_dirs'].each {
diff --git a/config/travis/deploy_github_pages.sh b/config/travis/deploy_github_pages.sh
index 2d8909741ab..964c715d04a 100755
--- a/config/travis/deploy_github_pages.sh
+++ b/config/travis/deploy_github_pages.sh
@@ -14,7 +14,7 @@ cd build/docs/html5
git init
git config user.name 'Deployment Bot (Travis)'
-git config user.email 'deploy@travis-ci.org'
+git config user.moduleCode 'deploy@travis-ci.org'
git config credential.helper 'store --file=.git/credentials'
echo "https://${GITHUB_TOKEN}:@github.com" > .git/credentials
diff --git a/copyright.txt b/copyright.txt
index 93aa2a39ce2..f1931159a8c 100644
--- a/copyright.txt
+++ b/copyright.txt
@@ -6,4 +6,12 @@ Copyright by Susumu Yoshida - http://www.mcdodesign.com/
Copyright by Jan Jan Kovařík - http://glyphicons.com/
- calendar.png
-- edit.png
+
+Copyright by roserodionova - https://www.freepik.com/
+- jelphabot.png
+- bot_logo.png
+- newlogo.png
+- logo.png
+
+Copyright by - https://www.pinclipart.com/pindetail/iioRTiJ_alarm-clock-comments-medication-reminders-icon-png-clipart/
+- reminder.png
diff --git a/debug.log b/debug.log
new file mode 100644
index 00000000000..b21f47af5c9
--- /dev/null
+++ b/debug.log
@@ -0,0 +1 @@
+[0301/142901.905:ERROR:crash_report_database_win.cc(428)] unexpected header
diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc
index 458e6134f45..6c05632d787 100644
--- a/docs/AboutUs.adoc
+++ b/docs/AboutUs.adoc
@@ -4,53 +4,58 @@
:imagesDir: images
:stylesDir: stylesheets
-AddressBook - Level 3 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. +
-_{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ +
+JelphaBot is based on https://github.com/nus-cs2103-AY1920S2/addressbook-level3[AddressBook (Level 3)]. It was developed by the https://github.com/AY1920S2-CS2103T-F09-2/main[CS2103T-F09-2] team. +
{empty} +
-We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore].
+The developers of Jelphabot are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore].
== Project Team
-=== John Doe
-image::damithc.jpg[width="150", align="left"]
-{empty}[http://www.comp.nus.edu.sg/~damithch[homepage]] [https://github.com/damithc[github]] [<>]
+=== Yao Jie Thng
-Role: Project Advisor
+image::yaojiethng.png[width="150",align="left"]
+{empty}[http://github.com/yaojiethng[github]] [<>]
+
+Role: Team lead +
+Responsibilities: Integration
'''
-=== John Roe
-image::lejolly.jpg[width="150", align="left"]
-{empty}[http://github.com/lejolly[github]] [<>]
+=== Jel Lim
-Role: Team Lead +
-Responsibilities: UI
+image::clouddoggo.png[width="150",align="left"]
+{empty}[https://github.com/Clouddoggo[github]] [<>]
+
+Role: Team Member +
+Responsibilities: Scheduling and Tracking
'''
-=== Johnny Doe
-image::yijinl.jpg[width="150", align="left"]
-{empty}[http://github.com/yijinl[github]] [<>]
+=== Amanda Lam
-Role: Developer +
-Responsibilities: Data
+image::alam8064.png[width="150",align="left"]
+{empty}[http://github.com/alam8064[github]] [<>]
+
+Role: Team Member +
+Responsibilities: Documentation
'''
-=== Johnny Roe
-image::m133225.jpg[width="150", align="left"]
-{empty}[http://github.com/m133225[github]] [<>]
+=== Eden Ong
+
+image::eedenong.png[width="150",align="left"]
+{empty}[http://github.com/eedenong[github]] [<>]
-Role: Developer +
-Responsibilities: Dev Ops + Threading
+Role: Team Member +
+Responsibilities: Testing
'''
-=== Benson Meier
-image::yl_coder.jpg[width="150", align="left"]
-{empty}[http://github.com/yl-coder[github]] [<>]
+=== Yap Dian Hao
+
+image::yapdianhao.png[width="150",align="left"]
+{empty}[http://github.com/yapdianhao[github]] [<>]
-Role: Developer +
+Role: Team Member +
Responsibilities: UI
'''
diff --git a/docs/ContactUs.adoc b/docs/ContactUs.adoc
index 81be279ef6d..6a588bcb570 100644
--- a/docs/ContactUs.adoc
+++ b/docs/ContactUs.adoc
@@ -2,6 +2,12 @@
:site-section: ContactUs
:stylesDir: stylesheets
-* *Bug reports, Suggestions* : Post in our https://github.com/se-edu/addressbook-level3/issues[issue tracker] if you noticed bugs or have suggestions on how to improve.
+* *Bug reports, Suggestions* : Post in our https://github.com/AY1920S2-CS2103T-F09-2/main/issues[issue tracker] if you notice bugs or have suggestions on how to improve.
* *Contributing* : We welcome pull requests. Follow the process described https://github.com/oss-generic/process[here]
-* *Email us* : You can also reach us at `damith [at] comp.nus.edu.sg`
+* *Email us* : You can also reach us at:
+** Thng Yao Jie: thngyaojie@u.nus.edu
+** Jel Lim: jel.lim@u.nus.edu
+** Amanda Lam: e0323403@u.nus.edu
+** Eden Ong: eden.ong@u.nus.edu
+** Yap Dian Hao: dian_hap_yao@u.nus.edu
+
diff --git a/docs/DevOps.adoc b/docs/DevOps.adoc
index 2aa5a6bc0c1..c71698901cd 100644
--- a/docs/DevOps.adoc
+++ b/docs/DevOps.adoc
@@ -1,4 +1,4 @@
-= AddressBook Level 3 - Dev Ops
+= jelphaBot - Dev Ops
:site-section: DeveloperGuide
:toc:
:toc-title:
@@ -34,7 +34,7 @@ When a pull request has changes to asciidoc files, you can use https://www.netli
Here are the steps to create a new release.
-. Update the version number in link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp.java`].
+. Update the version number in link:{repoURL}/src/main/java/seedu/jelphabot/MainApp.java[`MainApp.java`].
. Generate a JAR file <>.
. Tag the repo with the version number. e.g. `v0.1`
. https://help.github.com/articles/creating-releases/[Create a new release using GitHub] and upload the JAR file you created.
diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc
index 3d65905a853..f1725b65fd2 100644
--- a/docs/DeveloperGuide.adoc
+++ b/docs/DeveloperGuide.adoc
@@ -1,40 +1,124 @@
-= AddressBook Level 3 - Developer Guide
+= JelphaBot - Developer Guide
:site-section: DeveloperGuide
:toc:
-:toc-title:
-:toc-placement: preamble
+:toc-title: Table of Contents
+:toc-placement: macro
+:toclevels: 4
:sectnums:
:imagesDir: images
:stylesDir: stylesheets
:xrefstyle: full
+:icons: font
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
-:warning-caption: :warning:
+:important-caption: :heavy_exclamation_mark:
endif::[]
-:repoURL: https://github.com/se-edu/addressbook-level3/tree/master
+:repoURL: https://github.com/AY1920S2-CS2103T-F09-2/main
-By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT`
+[.text-center]
+By: `AY1920S2-CS2103T-F09-2` Since: `Jan 2020` Licence: `MIT` +
+{blank} +
+{blank} +
+A0190055L Ong Eden +
+A0187819J Amanda Lam +
+A0188384M Lim We Si, Jel +
+A0184679H Yap Dian Hao +
+A0187280Y Thng Yao Jie
-== Setting up
-Refer to the guide <>.
+<<<
+toc::[]
+<<<
+
+== Preface
+
+=== Introduction
+
+JelphaBot is *a desktop application for managing tasks* for NUS students.
+JelphaBot is designed to allow these students to manage tasks conveniently and aids students by *allowing important tasks to be easily recognised*.
+
+Users enter commands in JelphaBot through a *Command Line Interface* (CLI).
+However, a Graphical User Interface (GUI) is still used for improved design and user experience.
+
+JelphaBot is based on the AddressBook-Level3 (AB3) project created by SE-EDU initiative at https://se-education.org
+
+=== Purpose of this Document
+
+The following section describes the software architecture and design decisions behind the implementation of JelphaBot.
+This guide is intended for developers who wish to maintain, modify or understand the software development behind our application.
+The guide is divided into various sections.
+First, it explores the overarching architecture of the software before exploring each individual component, as well as the individual implementations of each distinct feature.
+
+The guide is designed to be read as-needed, new developers can choose to start from the overarching view before narrowing down to the specific implementation they require.
+
+This Developer Guide consists of the following sections:
+
+* <> - Assists new developers in cloning and initializing a copy of JelphaBot.
+* <> - Provides an overview of the architecture design.
+* <> - Brief explanation of how features in JelphaBot were implemented on top of AB3, and explains the design considerations of these implementations.
+* <> - A guide for generating and publishing documentation.
+* <> - A guide for developers to set up and run test code.
+* <> - A guide for developers to build, test and release JelphaBot.
+
+<<<
+
+=== Notation used in this Guide
+
+.Common symbols used throughout this guide.
+[width="90%",cols="^15%,85%"]
+|===
+| `markdown` | A Java method or class
+| *_bold italics_* | A command which can be called in JelphaBot. +
+Sections presented in ALL CAPS represent command parameters.
+ifdef::env-github[]
+| :bulb: | Tips and tricks that might be useful
+| :information_source: | Additional information that is good to know
+| :heavy_exclamation_mark: | Important pointers to take note
+endif::[]
+ifndef::env-github[]
+a|TIP: {blank}| Tips and tricks that might be useful
+a|NOTE: {blank}| Additional information that is good to know
+a|IMPORTANT: {blank}| Important pointers to take note
+endif::[]
+// also known as TIP, NOTE, IMPORTANT
+|===
+
+<<<
+
+== Setting Up
+
+Refer to the guide link:{repoURL}/blob/master/docs/SettingUp.adoc[here].
+
+<<<
== Design
+JelphaBot is a desktop app built in Java based on the AddressBook-Level3 project created by the SE-EDU initiative, and inherits its architectural design.
+The software is split into various components, each with its own package.
+Each component is in charge of a single aspect of the software.
+
+[TIP]
+The data in JelphaBot is stored as .json files in the `data` subdirectory.
+
+//tag::designarchitecture[]
[[Design-Architecture]]
=== Architecture
-.Architecture Diagram
-image::ArchitectureDiagram.png[]
+The Architecture Diagram given below explains the high-level design of the App.
-The *_Architecture Diagram_* given above explains the high-level design of the App. Given below is a quick overview of each component.
+.Architecture Diagram for JelphaBot
+image::ArchitectureDiagram2.png[]
[TIP]
-The `.puml` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder.
-Refer to the <> to learn how to create and edit diagrams.
+The `.drawio` files used to create diagrams in this document can be found in the link:{repoURL}/tree/master/docs/diagrams/[diagrams] folder.
+To update a diagram, import the `.drawio` file to the https://draw.io[webapp].
+
+<<<
+Given below is a quick overview of each component.
-`Main` has two classes called link:{repoURL}/src/main/java/seedu/address/Main.java[`Main`] and link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`]. It is responsible for,
+`Main` has two classes called link:{repoURL}/blob/master/src/main/java/seedu/jelphabot/Main.java[`Main`] and link:{repoURL}/blob/master//src/main/java/seedu/jelphabot/MainApp.java[`MainApp`].
+It is responsible for,
* At app launch: Initializes the components in the correct sequence, and connects them up with each other.
* At shut down: Shuts down the components and invokes cleanup method where necessary.
@@ -53,198 +137,939 @@ The rest of the App consists of four components.
Each of the four components
-* Defines its _API_ in an `interface` with the same name as the Component.
+* Defines its API in an `interface` with the same name as the Component.
* Exposes its functionality using a `{Component Name}Manager` class.
-For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class.
+For example, the `Logic` component defines it's API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class.
-.Class Diagram of the Logic Component
-image::LogicClassDiagram.png[]
+<<<
[discrete]
==== How the architecture components interact with each other
-The _Sequence Diagram_ below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
+The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
.Component interactions for `delete 1` command
-image::ArchitectureSequenceDiagram.png[]
+image::interaction.png[]
+
+The subsequent sections detail how each component is implemented and its interactions with other components.
-The sections below give more details of each component.
+<<<
[[Design-Ui]]
=== UI component
-.Structure of the UI Component
+The Ui Component handles interactions between the user and the application.
+This includes input fields where commands are entered as well as translations of data in the Model Component to a visual representation in the interface.
+
+.Class Diagram of the UI Component
image::UiClassDiagram.png[]
-*API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`]
+[width="750"]
+*API* : link:{repoURL}/blob/master/src/main/java/seedu/jelphabot/ui/Ui.java[`Ui.java`]
-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class.
+The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `CalendarDayCard`, `ResultDisplay`, `TaskListPanel`, `StatusBarFooter` etc.
+All these, including the `MainWindow`, inherit from the abstract `UiPart` class.
-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`]
+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}/blob/master/src/main/java/seedu/jelphabot/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/blob/master/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`]
The `UI` component,
* Executes user commands using the `Logic` component.
* Listens for changes to `Model` data so that the UI can be updated with the modified data.
+<<<
+
[[Design-Logic]]
=== Logic component
+The Logic component handles the business logic after a command is executed.
+
[[fig-LogicClassDiagram]]
.Structure of the Logic Component
image::LogicClassDiagram.png[]
+[width="750"]
*API* :
-link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`]
+link:{repoURL}/blob/master/src/main/java/seedu/jelphabot/logic/Logic.java[`Logic.java`]
-. `Logic` uses the `AddressBookParser` class to parse the user command.
-. This results in a `Command` object which is executed by the `LogicManager`.
-. The command execution can affect the `Model` (e.g. adding a person).
-. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
-. In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user.
+. `Logic` uses the `JelphaBotParser` class to parse the user command.
+. This results in a `Command` object which is executed by the `LogicManager`.
+. The command execution can affect the `Model` (e.g. adding a task).
+. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
+. In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user.
+<<<
Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` API call.
.Interactions Inside the Logic Component for the `delete 1` Command
image::DeleteSequenceDiagram.png[]
-NOTE: The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+<<<
[[Design-Model]]
=== Model component
+The Model component provides an internal data representation of all tasks stored in JelphaBot, as well as methods to modify that data.
+
.Structure of the Model Component
image::ModelClassDiagram.png[]
-*API* : link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model.java`]
+[width="750"]
+*API* : link:{repoURL}/blob/master/src/main/java/seedu/jelphabot/model/Model.java[`Model.java`]
The `Model`,
* stores a `UserPref` object that represents the user's preferences.
-* stores the Address Book data.
-* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
+* stores JelphaBot data.
+* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other three components.
-[NOTE]
-As a more OOP model, we can store a `Tag` list in `Address Book`, which `Person` can reference. This would allow `Address Book` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object. An example of how such a model may look like is given below. +
- +
-image:BetterModelClassDiagram.png[]
+//[NOTE]
+//As a more OOP model, we can store a `Tag` list in `JelphaBot`, which `Task` can reference. This would allow `JelphaBot` to only require one `Tag` object per unique `Tag`, instead of each `Task` needing their own `Tag` object. An example of how such a model may look like is given below. +
+// +
+//image:BetterModelClassDiagram.png[]
+
+<<<
[[Design-Storage]]
=== Storage component
+The Storage component manages storing and retrieving of data onto local files in .json format.
+
.Structure of the Storage Component
-image::StorageClassDiagram.png[]
+image::Storage.png[]
-*API* : link:{repoURL}/src/main/java/seedu/address/storage/Storage.java[`Storage.java`]
+[width="750"]
+*API* : link:{repoURL}/blob/master/src/main/java/seedu/jelphabot/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 JelphaBot data in json format and read it back.
[[Design-Commons]]
=== Common classes
-Classes used by multiple components are in the `seedu.addressbook.commons` package.
+Classes used by multiple components are in the `seedu.JelphaBot.commons` package.
+This includes classes which implement utility functions which can be used by all other components.
== Implementation
This section describes some noteworthy details on how certain features are implemented.
+=== Tab System
+
+Users may experience information overload when introduced to the large number of features offered by JelphaBot.
+To prevent users from being overwhelmed, the available commands in Jelphabot are organised into various tabs according to their respective functionalities.
+JelphaBot contains 5 different tabs, each displaying a specific set of information and relevant functionality.
+
+* *Summary Tab* - <> of the updates to the task list over the past day.
+* *Task List Tab* - <> in the task list.
+* *Calendar Tab* - <> in specific days or months.
+* *Productivity Tab* - <> through metrics such as task completion rate.
+* *Reminder Tab* - <> upcoming reminders.
+
+// tag::changetab[]
+[[ChangeTab]]
+==== Switching between Tabs in Main Window
+
+To use the different features, we have also implemented commands for users to switch between the 5 tabs.
+
+.List of applicable Switch Tab commands.
+[width="70%",cols="45%,60%"]
+|===
+|Command |Tab switched to
+
+|*_summary_*, *_:s_*| Summary
+|*_list_*, *_:t_*| Task List
+|*_calendar_*, *_:c_*| Calendar
+|*_productivity_*, *_:p_*|Productivity
+|*_remindertab_*, *_:r_*|Reminder
+|===
+
+NOTE: *_list_* is used instead of *_task list_* to keep the relevant command short. +
+Conventionally, the shortcut is devrived from first letter of each tab label.
+
+Each respective shortcut also has the respective letter bolded in the Tab Panel of the User Interface.
+Shortcuts are case insensitive.
+
+.View of currently implented tabs in JelphaBot
+image::TabPresentationFormat.png[]
+
+<<<
+Tab changing in the application is defined using a `SwitchTab` enumeration.
+Tab changes are called at the end of a command by reading the private attribute `toSwitch` in `CommandResult`.
+To initiate a tab switch, the `Command` which returns the `CommandResult` with the corresponding value of `toSwitch`, set with the method `isShow{tabLabel}`, where `{tabLabel}` refers to the name of the tab defined in `SwitchTab`.
+
+When the tab of the application is changed, we need to update the:
+
+* `MainWindow` component so that the `SwitchTab` attribute in `MainWindow` reflects the new current tab, since this is used to check if a command can be executed,
+* `UI` component so that the panels display the information that is relevant to the tab.
+
+As an example, the figure below shows the sequence diagram of when a user executes the *_:s_* or *_summary_* command.
+
+[[Summary-SwitchTab-Sequence-Diagram]]
+.Sequence diagram of execution of the *_summary_* command
+image::SummarySwitchTabSequenceDiagram.png[]
+
+Upon execution of the *_:s_* command, `SummaryCommand#generateCommandResult()` will generate a `CommandResult` whose `SwitchTab` attribute is set to `SUMMARY` and return it to the `LogicManager`.
+Upon execution of the *_:s_* command, `SummaryCommand#generateCommandResult()` will generate a `CommandResult` whose `SwitchTab` attribute is set to `SUMMARY` and return it to the `LogicManager`.
+Now, the updates can be done for the respective components:
+
+* `UI` component: `MainWindow` calls `MainWindow#executeCommand()`, to retrieve the tab to be changed to and updates the current tab stored in its `SwitchTab` attribute by calling `CommandResult#isShow{tabLabel}()` where `{tabLabel}` is the tab to switch to.
+The display panel is updated by calling `MainWindow#handle{tabLabel}` where `{tabLabel}` is the tab to switch to.
+// end::changetab[]
+
+<<<
+// tag::summary[]
+=== Summary feature (Eden)
+
+JelphaBot has a Summary feature which provides an overview of the tasks due within the day as well as all tasks that have been complete within the day.
+
+This feature comes in the form of a summary panel, which comprises of two sections for the tasks due within the day and the tasks completed within the day respectively.
+
+For each task shown only details such as the Module Code and the Description are shown.
+
+Once the user marks a task due within the day as complete, it will automatically appear under the tasks completed within the day.
+
+[NOTE]
+If the user marks a task as completed, and immediately deletes the task from the task list, it will not appear in the summary screen.
+
+==== Implementation
+
+The implementation of this panel is facilitated by the `summary` package.
+
+Upon creation, the `Summary` object obtains the main task list from `Model`.
+The task list is then filtered with the help of `TaskDueWithinDayAndIncompletePredicate` and `TaskCompletedWithinDayPredicate` to obtain two lists with the desired tasks.
+
+These lists are stored as fields in the `Summary` class and are used to display the relevant information in the summary panel.
+
+<<<
+
+The following class diagram shows the structure of the classes in the `summary` package, in relation with their `Ui` counterparts.
+
+[[SummaryPanelClassDiagram]]
+.Class diagram of structure and relations of `Summary`, `SummaryPanel` and their components.
+image::SummaryPanelClassDiagram.png[]
+
+<<<
+To view the respective tasks, the user enters the *_summary_* command.
+Upon entry of the *_summary_* command, a `SummaryCommand` object will be created and `SummaryCommand#execute()`
+will be called.
+
+The following sequence diagram details the execution when `SummaryCommand#execute()` is called.
+
+.Sequence diagram of the creation of the `Summary` object when `SummaryCommand#execute()` is executed.
+image::SummaryCommandSequenceDiagram.png[]
+
+<<<
+
+==== Design considerations
+
+===== Aspect 1: The summary panel depends on the creation of new `Summary` objects to be updated
+
+* *Current solution*: Each time `DoneCommand` is executed, a new Summary object is to be created, and along with it the task lists contained inside the `Summary` object is updated and displayed on the summary panel as an updated list.
+** Pros: Easy to implement.
+Scalable when there are more things to be displayed on the summary panel.
+** Cons: Consecutive *_done_* commands are expensive, as the lists in the `Summary` object are reinitialised upon every *_done_* command.
+
+* *Alternative 1*: Have a single `Summary` object with underlying task list listeners to update the relevant task lists
+** Pros: Only one `Summary` object will have to be created for the duration the application is open.
+The task lists in the `Summary` object do not have to be reinitialised upon every *_done_* command.
+** Cons: May not be scalable if there are many things to be added to the summary panel in the future, as this will require more listeners, and the presence of many listeners may affect the performance of the application.
+
+* *Reason for chosen implementation:* The current implementation is more straightforward and simpler to implement, as the `SummaryList` and `SummaryPanel` which are used to display the contents of the summary panel simply need to extract and display the contents of the `Summary` object that was given, instead of requiring underlying listeners to keep track of whatever is happening within the application.
+
+<<<
+
+===== Aspect 2: Summary panel aesthetic improvements
+
+* *Current solution*: The Welcome header, tasks due today and tasks completed subsections have the same font and styling.
+The distinction between them is by the bigger font for the Welcome header, and the space separation between the subsections.
+This is done by having each section in their own separate `Vbox`.
+Everything shown on the panel is shown as plain text, with no additional styling.
+** Pros: This gives the summary panel a minimal look that is simple and easy to look at, while still providing the user with the relevant information that is needed.
+** Cons: Due to the implementation of the subsections as separate boxes of equal sizes that are scaled to fit the panel, there is a lot of unused space in between each subsection, if there are not enough tasks to fill in the space.
+This can be seen as a waste of space.
+* *Alternative 1*: Add font styling and section highlighting to different sections of the summary panel
+** Pros: Makes the summary panel more visually appealing, and makes each subsection more distinct from each other.
+** Cons: Does not solve the problem of unused space when there are not enough tasks to fill the space in each subsection.
+
+* *Reason for chosen implementation:* The current implementation is easier to implement and keeps the summary panel simple and easy to look at as it avoids the cluttering of the summary panel with too many different design elements.
+This makes it very user-friendly, and it also easily scalable in the future as each section is already partitioned accordingly, so future changes to the summary panel simply have to change the elements within each section.
+
+// end::summary[]
+
+<<<
+// tag::taskgroups[]
+=== Task Grouping feature in Task List tab (Yao Jie)
+
+==== Implementation
+
+The task category mechanism is facilitated by the `ViewTaskList` interface, which serves as a wrapper for any list of tasks. +
+The ViewTaskList interface supports methods that facilitate getting and iterating through the tasks contained within the list.
+This is to accommodate a common access for Tasks in `GroupedTaskList`, which contains multiple sub-lists. +
+The diagram below describes the class structure.
+
+.Class Diagram for Task List classes
+image::TaskListClassDiagram.png[]
+
+Grouping tasks into sub-lists is done through the `GroupedTaskList` class. +
+Each `GroupedTaskList` is a container for `ObservableList` objects, each containing a unique filter over the full task list.
+
+Each `GroupedTaskList` implements the following operations on top of those in `ViewTaskList`:
+
+* A enum class which describes the valid `Category` groupings, and the corresponding methods of getting these groupings from a `String`. +
+* An `ObservableList` of `SubgroupTaskList` that represents the sub-groupings of each corresponding `Category`.
+* A public method for instantiating a `GroupedTaskList` called `getGroupedList` with the return from `getFilteredTaskList()` as argument.
+* An iterator method which iterates through a list of `SubgroupTaskList`.
+
+Users can modify the `GroupTaskList` being displayed in the main panel by executing a `ListCommand`.
+The operation for retrieving the corresponding `GroupedTaskList` is exposed in the `Model` interface as `Model#getGroupedTaskList(Category category)`. +
+Currently, the supported groupings for JelphaBot are group by date (`GroupedTaskList.Category.DATE` and `GroupedByDateTaskList`) and group by module (`GroupedTaskList.Category.MODULE` and `GroupedByModuleTaskList`).
+
+The following diagram shows the sequence flow of a `ListCommand` which modifies the currently shown Task List:
+
+[[activity-swapping-groupedtasklist]]
+.Activity Diagram showing the tab switch for ListCommand
+image::ListCommandActivityDiagram.png[]
+
+<<<
+Given below is an example usage scenario and how the task category mechanism behaves at each step.
+
+*Step 1.* The user launches the application for the first time.
+The `MainWindow` will be initialized with `GroupedTaskListPanel` as a container for GroupedTaskList model objects.
+The panel is populated with sublists defined in `GroupedByDateTaskList`.
+
+*Step 2.* The user executes *_list model_* to switch to category tasks by module code instead. `GroupedTaskListPanel` is repopulated with sublists defined in `GroupedByModuleTaskList`.
+
+[NOTE]
+If the user tries to switch to a `Cateory` which is already set, the command does not reinitialize the `GroupedTaskList` to prevent redundant filtering operations.
+
+As `GroupedTaskList` has more than one underlying `ObservableList`, tasks cannot be retrieved the usual way.
+Thus, the `get()` function defined in the `ViewTaskList` interface must be implemented and used instead. +
+The following diagram shows the process of retrieving a `Task` from `ViewTaskList` when it is an instance of `GroupedTaskList`:
+
+[[sequence-viewtasklist-get]]
+.Sequence Diagram for `ViewTaskList.get()`
+image::ViewTaskListGetSequenceDiagram.png[]
+
+As the index passed as an argument to `lastShownList.get()` is a cumulative index, the implementation of `get()` in `ViewTaskList` has to iterate through each `SubgroupTaskList` stored within.
+
+<<<
+Tasks are organized via a two-dimensional list.
+In this case, a `Task` is rendered into a `TaskCard`, and `TaskCard` elements are rendered within `SubGroupTaskListCell` elements which are listed in `SubgroupTaskListPanel`.
+A populated `SubgroupTaskListPanel` element is rendered as a `GroupedTaskListCell` which is listed in the top-level `GroupedTaskListCell`. +
+`SubgroupTaskListCell` and `GroupedTaskListCell` implement the `ListViewCell` interface of the `ListView` class provided by JavaFX.
+
+.Class Diagram for UI classes displaying `GroupedTaskList`
+image::TaskListPanelClassDiagram.png[]
+
+The detailed interactions are described in the diagram shown above.
+As can be seen, the distribution of `ListViewCell` elements follows the way tasks are distributed within the model classes.
+Each `SubgroupTaskListPanel` is displaying a singular `SubgroupTaskList`, which further contains a list of `Task` entities.
+
+The indexes displayed in each `TaskCard` is dynamically computed from a `NumberBinding` which computes the index of that element in the list.
+The `NumberBinding` observes the place of the task within the current `SubgroupTaskList` as well as the number of elements in the preceding sublists.
+The sum of both numbers gives the index for the current element, which is set using `setId()`. `TaskCard` elements are updated with `populateTaskElements()`.
+
+<<<
+Each `TaskCard` will also have a different visual presentation depending on the value of the `Priority` of the task.
+The method which adjusts the visual presentation of a `Task` is `applyPriorityMarkdown()`.
+
+The following images show how `Task` entities of different priorities are displayed: +
+
+.Markdown for Tasks of different priority. (Top to bottom: Normal, High, Low.)
+image::PriorityMarkupForTaskCards.png[]
+
+<<<
+
+==== Design Considerations
+
+===== Aspect 1: `ListCommand` swaps to a different `ViewTaskList`
+
+Refer to <> for the diagram describing this process.
+
+* *Current solution*: Initializes each grouped list as each `ListCommand` is called and stores the latest list as `Model.lastShownList`.
+** Pros: Easy to implement.
+Scalable when more groupings are added.
+** Cons: Consecutive `ListCommand` operations which swap between different categories are expensive as the list is reinitalized each time.
+** Cons: It is hard to keep track of the exact type of list in `lastShownList`, which may lead to unexpected behavior.
+* **Alternative 1:** Keep instances of all `GroupedTaskList` objects and update them as underlying Task List changes.
+** Pros: Consecutive `ListCommand` executions are less expensive.
+** Cons: All other commands that update the underlying list now have additional checks as each grouped list is updated.
+
+*Reason for chosen implementation:* +
+The current solution was chosen in order to accomodate more `Category` implementations in the future.
+With only two classes inheriting `GroupedTaskList`, it is entirely feasible to implement both.
+However, since only one `GroupedTaskList` will be used at any time, and to take into account possible performance savings, only one `GroupedTaskList` implementation will exist at any one time.
+
+===== Aspect 2: `get()` Task from `ViewTaskList` and iterate between Tasks.
+
+Refer to <> for the diagram describing this process.
+
+* *Current solution*: Implement `get()` and `Iterator` in `ViewTaskList`.
+** Pros: Easy to implement.
+Scalable when more groupings are added.
+** Cons: Consecutive `ListCommand` operations are expensive as the list is reinitalized each time.
+** Cons: It is hard to keep track of the exact type of list in `lastShownList`, which may lead to unexpected behavior.
+*** As a workaround, only operations defined in the `ViewTaskList` interface should be used.
+* **Alternative 1:** Keep instances of all `GroupedTaskList` objects and update them as underlying Task List changes.
+** Pros: Consecutive `ListCommand` executions are less expensive.
+** Cons: All other commands that update the underlying `UniqueTaskList` will result in multiple update calls to `ViewTaskList`.
+
+<<<
+
+*Reason for chosen implementation:* +
+The current solution was chosen with integration with other tabs in mind.
+This implementation can easily be expanded to other tabs in a future version if other tabs also inherit from `ViewTaskList`.
+This allows *_add_*, *_edit_*, *_delete_* and *_done_* commands to be executable from any tab, while still only requiring one `ViewTaskList` to be instantiated, which saves performance.
+
+//===== Aspect 3: Hide empty Categories in `GroupByDateTaskList`
+//
+//* *Current Solution*: UI displays problems from a `FilteredList` and use `filtered()` to hide empty categories without removing them.
+//** Rationale: These categories are meant to be reused when applicable tasks are added back to the list.
+//** Pros: The list categories do not have to be reinitalized as tasks are removed or added.
+//** Cons: Additional load on the UI as the Filtering happens constantly.
+//However, since there is a cap on five categories (so five `FilteredList` lists), it is unlikely to be significant.
+//** Cons: Inconsistent with the way filtering is done in `GroupByModuleTaskList`, which reduces control abstraction in `GroupedTaskList`.
+//* **Alternative 1:** Remove categories which are no longer used, and reinitialize them again when needed.
+//** Pros: Consecutive changes to the underlying Task List are less expensive if less lists are currently active.
+//** Pros: Enforce consistency with `GroupByModuleTaskList` which might allow some methods to be abstracted to parent class.
+//** Cons: Empty `SubgroupTaskList` members have to be hidden manually which requires complex logic in `SubgroupTaskListPanel`.
+//** Cons: Additional listeners have to be added (one for each category) to reinitialize empty categories.
+
+===== Aspect 3: Remove empty Categories in `GroupByModuleTaskList`
+
+* *Current Solution*: UI displays problems from a `FilteredList` and uses a `ListChangeListener` to maintain a set of unique module codes when the underlying task list is changed.
+The `ObservableSet` has a further `SetChangeListener` bound to it to remove categories that no longer contain any Tasks.
+This second listener directly removes unused categories from `GroupedByModuleTaskList`.
+** Pros: Consecutive changes to the underlying Task List are automatically reflected with a change in `SubgroupTaskList` categories.
+** Pros: The delegation of responsibilities between each `Listener` allows Single Responsibility Principle to be maintained.
+** Cons: Dependency between the two `Listener` classes has to be maintained.
+* **Alternative 1:** Hide categories which are no longer used by adding a filter to the Task List returned.
+** Pros: Easy to implement and understand.
+** Cons: Not practical: as more Module Codes are added to the Task List, it might cause more and more hidden categories to be created which are expensive to filter through.
+* **Alternative 2:** Abstract maintenance of the set of unique module codes to a `UniqueModuleCodeSet` class instanced in `UniqueTaskList`.
+** Pros: Easy to understand.
+Logic is further abstracted to a higher level and the new class is instanced together with the list that affects it.
+** Pros: The returned `ObservableSet` from `UniqueModuleCodeSet` can be made unmodifiable which would prevent unauthorized changes to the `ObservableSet` from other classes.
+** Cons: Implementation is challenging and prone to bugs, requiring significant testing.
+Due to the time of writing this Developer guide, the release is nearing V1.4 and time is spent fixing bugs for release instead.
+** This could be a proposed update in the future.
+
+*Reason for chosen implementation:* +
+The best solution would be to create a `UniqueModuleCodeSet` instanced in `UniqueTaskList`, which would have the best scalability and abstraction.
+In addition, since such a set would be updated regularly, less mantainence is needed inside classes that require a list of unique `ModuleCode` entities.
+However, due to time constraints, such an implementation was not chosen.
+However, the current solution mimics the best solution as closely as possible by using `SetChangeListener` to update the `SubgroupTaskList` list.
+This means that a returned `UnmodifiableObservableSet` from `UniqueModuleCodeSet` can be substituted easily whenever such a refactoring is done.
+// end::taskgroups[]
+
+<<<
+// tag::calendar[]
+=== Calendar feature (Amanda)
+
+JelphaBot has a calendar feature which provides an overarching view of users' schedules and to allow them to keep track of their due tasks.
+It is meant to provide a more fine-grained visualization than what is shown in the task list.
+
+This feature offers two main functions:
+
+** Displays an overview of tasks in calendar for a selected month and year
+** Displays a list of tasks due for a specified date
+
+==== Implementation
+
+The implementation of the main calendar panel is facilitated by the `CalendarMainPanel` class, which serves as the main container for this feature.
+This main container consists of a `SplitPane` comprising of a `CalendarPanel` on the right, which displays the calendar view in a month, and a `CalendarTaskListPanel` on the left to display specific tasks.
+
+The diagram below describes the class structure of the calendar class structure.
+
+.Class Diagram for Calendar classes
+image::CalendarUiClassDiagram.png[]
+
+<<<
+
+Upon initialisation of the `CalendarMainPanel`, the `CalendarPanel` would be set to display the current month and year calendar, with the dates filled up by `CalendarDayCard` by CalendarPanel#fillGridPane() with a `CalendarDate` starting from the first day of the current month.
+Today's date would also be highlighted, with `CalendarTaskListPanel` set to display the tasks due today by running Logic#getFilteredCalendarTaskList() and then Logic#updateFilteredCalendarTaskList() with a predicate to filter by today's date.
+
+The following diagram depicts how each individual day cell of the calendar will look like:
+
+.Expected display of dates on calendar
+image::CalendarDayCards.png[]
+
+After every execution of command, MainWindow#updateTasksInCalendarDayCards() will be run such that any commands that updates the JelphaBot task list (e.g `DoneCommand`, `DeleteCommand`, `EditCommand`) would be updated by the dot indicators in the calendar.
+
+**Function 1: Displays an overview of tasks in calendar for a selected month and year**
+
+There are 2 commands that users can issue to perform function 1:
+
+1. *_calendar today_*: Displays calendar for the current month with today's date highlighted, and its corresponding tasks due listed. +
+2. *_calendar MONTHYEAR_*: Displays calendar for the month and year specified, with the first day of the month highlighted, and its corresponding tasks due listed (e.g. calendar Apr-2020).
+Refer <>, for the diagram describing this process.
+
+Upon execution of the *_calendar MONTHYEAR_* or the *_calendar today_* command, CalendarCommand#execute() will run `updateFilteredCalendarTaskList()` to filter the task list to display the tasks on the `CalendarTaskListPanel` according to the first day of the *_MONTHYEAR_* or the tasks due *_today_* respectively.
+The filtering of the tasks according to date is done using the `TaskDueWithinDayPredicate`.
+A distinct `CommandResult` would then be generated according to the input command and is returned to the `LogicManager`.
+Finally, the `CommandResult` is passed to the `MainWindow` in UI. Now, the updates can be done for the respective components:
+
+`UI` Component: Using the CommandResult, `MainWindow` calls `MainWindow#updateCalendarMainPanel()`, which is then passed to call `CalendarMainPanel#updateCalendarPanel()`.
+For the *_calendar MONTHYEAR_* command, this updates the `CalendarPanel` display with the respective *_MONTHYEAR_* view, and highlights the first day of the month.
+For the *_calendar today_* command, this updates the `CalendarPanel` display to the current month and year, with today's date highlighted.
+
+<<<
+The following example sequence diagram shows you how the *_calendar MONTHYEAR_* (e.g. _calendar Apr-2020_) command works.
+
+[[Calendar-MonthYear-SequenceDiagram]]
+.Sequence diagram after running `calendar Apr-2020`
+image::CalendarViewSequenceDiagram.png[]
+
+**Function 2: Display a list of tasks due for a selected date in the month**
+
+In order to display the task list for specific input dates, the user enters the *_calendar DATE_* command +
+(e.g. calendar Jan-1-2020).
+
+NOTE: Only a date belonging in the current displayed month on the `CalendarPanel` would be highlighted after processing the `calendar DATE` command.
+A date that falls in other month and years would just display its corresponding tasks due on the `CalendarTaskListPanel`.
+
+The implementation of the previous two calendar commands (*_calendar DATE_* and *_calendar today_*) are largely similar and run in the same process.
+The only exception is regarding the *_calendar DATE_* command which fulfills **Function 2** listed above, where the `GridPane` in `CalendarPanel` is not altered by running CalendarPanel#fillGridPane() unlike the other two commands fulfilling **Function 1**.
+Only `CalendarTaskListPanel` is updated.
+
+<<<
+
+The following diagram shows the sequence flow for variants of these three calendar commands which modifies the `CalendarMainPanel`:
+[[Calendar-ActivityDiagram]]
+.Activity Diagram showing the updating of `CalendarMainPanel`
+image::CalendarCommandActivityDiagram.png[]
+
+<<<
+
+==== Design Considerations
+
+===== Aspect 1: How the user can navigate between specific dates and change the calendar month view
+
+* *Current Solution:* Use the same `calendar` command word for both viewing tasks in specific dates, and changing the calendar view.
+The next input following the command word (*_DATE_*, *_MONTHYEAR_*, *_today_*) is then parsed separately to give different command results.
+** Pros: Easier and more understandable for user interactions.
+** Pros: More open and accessible to future implementations regarding the calendar feature.
+** Cons: Implementation in the `CalendarCommand` class might seem a bit bulky.
+* **Alternative 1:** Use completely separate commands for viewing tasks in specific dates and changing the calendar view.
+** Pros: Less chance of a parse exception, with more precise error messages when invalid command formats are input by the user.
+** Cons: Certain areas of the code might be repetitive.
+** Cons: Less intuitive for users to use.
+
+*Reason for chosen implementation:* +
+The current solution is more user-friendly as it reduces the number of varying commands that users have to remember in order to access the respective information.
+Additionally, upcoming changes and future implementations can be easily integrated into the existing code base as well.
+
+<<<
+
+===== Aspect 2: Method of storing `ObservableList` of tasks for each day card (Implementation of the Dot Indicator)
+
+* *Current Solution:* Each `CalendarDayCard` stores a filtered list of tasks due on its specific date.
+This is done by obtaining all the tasks in the task list from Logic#getFilteredTaskList() and applying a filter function with the `TaskDueWithinDayPredicate`, specifically with the date of the day card.
+The list of tasks stored for each day card in the calendar panel would be re-filtered after the execution of each command.
+** Pros: Do not have to manually update the tasks stored in each `CalendarDayCard` (e.g add and remove manually in the separately stored copy)
+** Cons: Completely reliant on the main task list, possible errors might be carried over.
+* **Alternative 1:** Use a static HashMap of Dates as keys and a list of tasks due in that date as values.
+** Pros: Retrieving the tasks in a specific date and storing in the day card is fast - can be done in O(1) time.
+** Cons: Implementation would be much more complex.
+** Cons: Updating of this HashMap of the tasks as the main task list is being edited constantly can be very tedious.
+
+*Reason for chosen implementation:* +
+The current solution is easier to implement since we are filtering the tasks we want to see directly from the main task list.
+This reduces the amount of methods to implement over various class and components as constant updates of the tasks in each day card of the calendar is done.
+The ease of implementation is crucial given the tight deadlines we have to meet for the project.
+// end::calendar[]
+
+<<<
+
+// tag::productivityImplementation[]
+=== Productivity feature (Jel)
+
+JelphaBot has a productivity panel of this feature which provides an overarching view of user's overall productivity.
+
+The view of this panel is facilitated by the productivity package that extracts the relevant data and displays them as a cohesive view.
+The productivity package supports the creation of `TimeSpentToday`, `RunningTimers` and `TasksCompleted` instances.
+Each of these classes iterate through the tasks contained within the task list. +
+Below is a class diagram of the related productivity classes:
+
+.Class diagram showing the structure and relations of `Productivity`, `ProductivityPanel` and their components.
+image::ProductivityClassDiagram.png[width=540]
+
+This feature offers two main functions and one panel for visualisation:
+
+** Start timer for a task.
+** Stop running timer for a task.
+** Productivity panel under Productivity tab.
+
+<<<
+
+==== Implementation
+
+Text rendered onto the productivity panel is retrieved from the `Productivity` class. +
+A `Productivity` object is a container for the objects responsible for the sub-parts of the panel, namely `TimeSpentToday`, `RunningTimers` and `TasksCompleted`.
+Each of these have their respective String representations which will be used in rendering the panel.
+
+`TimeSpentToday` implements the following operations:
+
+* An iterator method `getTimeSpent()` which iterates through a list of `ObservableList`.
+** This iterator will extract the duration field of each task.
+* A `toString()` method which returns the sum of duration (i.e. time spent) of tasks under 3 different categories: "due today", "due in next 6 days" and "due after 6 days".
+
+[NOTE]
+Each time `toString()` is called, `getTimeSpent()` is called thrice; once each for the 3 categories.
+
+`RunningTimers` implements the following operations:
+
+* An iterator method `getTasksWithTimers()` which iterates through a list of `ObservableList`.
+** This iterator will extract the description and deadline of tasks with timers that have been started.
+* A `toString()` method which returns the tasks with running timers.
+
+`TasksCompleted` implements the following operations:
+
+* An iterator method `getCompletionStatus()` which iterates through a list of `ObservableList`.
+** This iterator will extract the number of tasks completed under the "due today" category.
+* An iterator method `getOverdueStatus()` which iterates through a list of `ObservableList`.
+** This iterator will extract the number of tasks that are incomplete and past their due date.
+* A getter method which returns the percentage of tasks completed that are under the "due today" category.
+* A `toStringArray()` method which returns the task completion status, JelphaBot's response to the user's productivity, as well as number of overdue tasks.
+
+Information from all three objects are subsequently rendered onto the panel through `ProductivityCard` and `ProductivityPanel`.
+// end::productivityImplementation[]
+
+// tag::productivityFunctions[]
+Assuming that the task list is not empty, the following describe the flow of _start 1_ and _stop 1_ which modify the currently shown productivity panel:
+
+<<<
+
+**Function 1: Starts timer for a specified task** +
+In order to start timing a task, the user enters *_start INDEX_* command (e.g. _start 1_).
+
+Upon successful execution of the command, the productivity tab displays the task being timed under the Running Timer(s) header.
+The following diagram shows the flow of _start 1_ which modifies the current view of the productivity panel:
+
+[[activity-settingProductivitylist]]
+.Activity Diagram showing the setting of `Productivity` in the `ProductivityList`
+image::StartActivityDiagram.png[]
+
+To update the productivity panel to reflect the changes, a new `Productivity` object will first be created, replacing the existing `Productivity` object in the `ProductivityList`.
+Each time a new `Productivity` object is created, its corresponding booleans will dictate whether the sub-parts (i.e. `TimeSpentToday`, `RunningTimers` and `TasksCompleted`) are to be replaced with new objects.
+As the command executed is *_start_*, a new `RunningTimers` object is created.
+As detailed above, the iterator method in `RunningTimers` will be called and a new `String` representation to be displayed onto the productivity panel will be created.
+This `String` is subsequently rendered onto the panel under the Running Timer(s) header.
+
+<<<
+
+The following diagram shows the flow which updates the Running Timer(s) section in the productivity panel:
+
+[[activity-updatingProductivityPanel]]
+.Activity Diagram showing the updating of Running Timer(s) in the productivity panel
+image::TimerPanelActivityDiagram.png[]
+
+<<<
+
+**Function 2: Stops timer for a specified task** +
+In order to stop timing a task, the user enters *_stop INDEX_* command (e.g. _stop 1_)
+
+Upon successful execution of the command, the productivity tab removes the task being timed under the Running Timer(s) header.
+Removing a task from the Running Timer(s) header is similar to adding it, as illustrated by the Activity Diagram <>.
+Under the Time Spent header, the total time spent will be increased in the respective subheaders depending on the date that the task is due.
+
+[IMPORTANT]
+Attempting to start a timer for a task which is marked as completed or stop a task with no active timer results in the command execution failing and an exception thrown.
+
+.Sequence Diagram after running _stop 1_
+image::StopSequenceDiagram.png[]
+// end::productivityFunctions[]
+
+<<<
+// tag::productivityDesign[]
+==== Design Considerations
+
+===== Aspect 1: Rendering sub-parts of productivity panel
+
+* *Current solution*: Render each sub-part (i.e. task completion rate, time spent and running timers) only when that part needs to be updated.
+All 3 parts are rendered on to the same card.
+** Pros: Easy to implement and reduces waste of computational power.
+** Cons: As all parts are displayed on the same card, if there happens to be problem in other parts of the card, all parts will be affected.
+* *Alternative 1*: Abstract each part to a separate card and render all cards onto the same panel.
+** Pros: Allows other parts to be rendered even when there is error on one part.
+Additionally, it is easier to identify bugs when there is an error in displaying.
+** Cons: Difficult to implement as current view is generated from a ListView but with a single card.
+Thus, abstracting and refactoring will be costly and hard to debug.
+* *Alternative 2*: Employ multi-threading for rendering each sub-part.
+** Pros: No need to use 3 different booleans when updating view.
+Code base will be cleaner and more readable.
+** Cons: Unsure if cost of multi-threading less than that of constructing 3 instances for rendering the productivity panel view.
+
+*Reason for chosen implementation:* +
+Minimal computational power is wasted as only the parts that requires re-rendering are recomputed.
+Moreover, it is easy to implement and easily extendable to display
+
+===== Aspect 2: Restriction of functionality while timer is running
+
+* *Current solution*: Tasks with running timers cannot be edited or marked as done.
+** Pros: Other functionality are still available for use.
+Thus, overall user experience is not affected.
+** Cons: User is unable to make changes to the task being timed nor mark it as complete.
+* *Alternative 1*: Allow users to edit task while timer is running.
+** Pros: User is able to use all features without restriction.
+** Cons: Difficult to implement as the Task model requires a new Task to replace the old Task when edit command is executed.
+More storage space is also needed to store the additional start time field for each task.
+* *Alternative 2*: Allow users to mark tasks as done while timer is running.
+** Pros: Similar to the above, user is able to use all features without restriction.
+** Cons: User may have forgotten about running timer and wish to collect such information.
+However, there is currently no function that supports undoing commands or unmarking a completed task.
+
+<<<
+
+*Reason for chosen implementation:* +
+Editing and marking a task require the creation of a new task which overwrites the existing task.
+Use of space is also minimised and less computational power is used as no new Task objects have to be created.
+
+===== Aspect 3: Productivity panel visualisation
+
+* *Current solution*: Separating sub-parts by paragraphs and including progress bar for tasks completed.
+** Pros: Easy to see at a glance which parts are which.
+** Cons: Text under Running Timer(s) can appear wordy.
+As number of running timers increase, more text is added under Running Timer(s).
+* *Alternative 1*: Highlight displayed module code and deadline in alternating colours.
+** Pros: Visually more appealing and looks less like a long list is tasks thus motivating the user to complete his/her tasks.
+** Cons: Does not resolve the issue of having too many words under the sections.
+* *Alternative 2*: Only show limited number of tasks (e.g. 3) whose timers were started, in order of priority and time when timers were started.
+** Pros: Allows user to focus on tasks at hand.
+** Cons: User might forget about other tasks whose timers were started and not complete them on time.
+
+*Reason for chosen implementation:* +
+We feel that paragraphing increases readability and the progress bar provides visual aid.
+Addtionally, including more images or pie charts may confuse or distract users from their tasks which defeats the purpose of JelphaBot.
+Restricting the number of running timers listed will also adversely affect user experience as it does not provide any tangible benefits.
+// end::productivityDesign[]
+
+<<<
+// tag::reminder[]
+=== Reminder feature (Dian Hao)
+
+JelphaBot has a reminder feature that reminds users whenever they have tasks that will be overdue soon.
+This feature offers two main functions:
+
+** Adds a reminder to a task.
+** Delete a reminder that is associated to a task.
+
+==== Classes for Reminder feature in Model
+
+The `Reminder` feature was implemented by a new set of classes to `Model`.
+A new `Reminder` class is stored in Jelphabot's `UniqueReminderList`, which consists of a list of `Reminder` s.
+Each `Reminder` consists of 3 objects: +
+** `Index`**: the `Task` 's index of which the user wants to be reminded for. +
+** `ReminderDay`**: the number of days before the `Task` 's deadline that the user wants to be reminded for. +
+** `ReminderHour`**: the number of hours before the `Tasks` 's deadline that the user wants to be reminded for. +
+
+The following class diagram summarizes shows the relationship between the classes.
+
+
+[[class-Reminder]]
+.Reminder Class Diagram in the Model component
+image::Reminderclass.png[]
+
+<<<
+
+==== Implementation
+
+**Function 1: Creates a reminder for a specified task** +
+To add a reminder to a certain task, the user enters the _reminder INDEX days/DAYS hours/HOURS_ command.
+(e.g, reminder 2 days/2 hours/1) +
+
+The `Logic` `execute()` method creates a `ReminderCommand` from the input string by parsing the input according to the command word and several other attributes.
+Next, the input string is converted into `Index`,
+`ReminderDay`, `ReminderHour`, and a `Reminder` object with these properties are forwarded to `Model`. +
+
+The `Model` first checks the validity of the attributes respectively.
+The valid `Reminder` is then added to the `UniqueReminderList` after checking that there are no other `Reminder` with the same `Index`. +
+
+After the above actions are correctly performed, the `Logic` fires the `Storage` to save the `Reminder`.
+
+Upon successful execution of the command, the user adds a reminder associated to the task at `INDEX`.
+Upon exiting JelphaBot, the reminder will be saved.
+By the next time the users starts JelphaBot, it will remind the user should the task's due date fall within the period set by the user from the current date. +
+
+The sequence diagram for interactions between the `Logic`, `Model`, and `Storage` is shown below.
+
+[[sequence-addReminder]]
+.Sequence Diagram after running _reminder 2 days/2 hours/1_
+image::AddReminderSequenceDiagram.png[]
+
+[[reference-getCommandResult]]
+.The reference frame of getting the `CommandResult` in the `Logic` component.
+image::getCommandResultReferenceDiagram.png[]
+
+[[reference-addReminder]]
+.The reference frame of adding the `Reminder` in the `Model` component.
+image::addReminderReferenceDiagram.png[]
+
+[[reference-saveJelphaBot]]
+.The reference frame of saving a `Reminder` by the `Storage` component.
+image::saveJelphaBot.png[]
+
+[NOTE]
+If the user attempts to add a reminder to tasks that have reminders, the command will fail to execute.
+The user also will not need to set reminders to tasks that are complete.
+However, if tasks that has reminders are not completed, JelphaBot will still warn the user.
+
+**Function 2: Deletes a reminder for a specified task** +
+To delete a reminder associated to a certain task, the user enters the `delrem INDEX` command.
+(e.g. delrem 2)
+
+The interaction between components is similar to adding a `Reminder`.
+A key difference that this command removes the `Reminder` that reminds the `Task` at `INDEX` from the `UniqueReminderList`.
+Moreover, `delrem` command requires that the `Reminder` with `INDEX` is in the list.
+
+Upon successful execution of the command, the reminder of the task at `INDEX` is removed.
+
+<<<
+
+==== Design Considerations
+
+===== Aspect 1: Implementing `Reminder` object
+
+* *Current solution:* Implement `Reminder` as a standalone class
+** Rationale: A `Reminder` is an object, with the same hierarchy as the `Task` class, with similar attributes.
+** Pros: Fully capture the idea of an object-oriented design and robust in handling future changes.
+** Cons: An additional storage is required to store the `Reminder` objects, which causes overhead while reading from and writing to json files.
+* *Alternative 1:* Design `Reminder` as one of the attributes of a `Task`
+** Rationale: A `Reminder` can also be seen as one of `Task` 's properties, analogous to `Description` and other properties.
+** Pros: Easy to implement.
+Concurrent fetching and storing from the json files while reading and writing `Task`.
+** Cons: A `Reminder` has to remind users the moment when Jelphabot is booted.
+At that instance, `Storage` has not started to read `Task` from the json files yet, therefore the `Reminder` could not be read beforehand.
+
+*Reason for chosen implementation:* +
+We decided to choose the current solution due to the dynamic nature of tasks and users' needs.
+For upcoming changes in the future, it is easier to implement by adding similar classes or attributes to the existing design.
+
+===== Aspect 2: Rendering `Reminder` on `ReminderListPanel`
+
+* *Current solution:* Shows the `ModuleCode`, `Description`, and `DateTime` of the `Task` that is being reminded, the respective `ReminderDay` and `ReminderHour`.
+** Pros: convenient and simple to understand.
+Users only need to refer to the `TaskListPanel` to look at the details of the `Task`.
+** Cons: FXML styling will be squeezy.
+* *Alternative 1:* Shows the `Reminder` similar to how the `Task` is displayed.
+** Pros: Simple, as it only shows the details of the `Reminder`.
+** Cons: Users need to constantly refer to the `TaskListPanel` for details.
+Both panels have an `Index` listed, which may cause confusion.
+
+*Reason for chosen implementation:* +
+We decided to choose the current solution after considering users' needs and convenience of fully using the `Reminder` s.
+Users do not need to switch back and forth between tabs to refer between `Task` s and `Reminder` s, which saves time that can be better spent by completing the `Task` s.
+// end::reminder[]
+
+<<<
// tag::undoredo[]
-=== [Proposed] Undo/Redo feature
+=== Undo/Redo feature [Proposed to implement in v2.0]
+
==== Proposed Implementation
-The undo/redo mechanism is facilitated by `VersionedAddressBook`.
-It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`.
+The undo/redo mechanism is facilitated by `VersionedJelphaBot`.
+It extends `JelphaBot` with an undo/redo history, stored internally as a `jelphaBotStateList` and `currentStatePointer`.
Additionally, it implements the following operations:
-* `VersionedAddressBook#commit()` -- Saves the current address book state in its history.
-* `VersionedAddressBook#undo()` -- Restores the previous address book state from its history.
-* `VersionedAddressBook#redo()` -- Restores a previously undone address book state from its history.
+* `VersionedJelphaBot#commit()` -- Saves the current JelphaBot state in its history.
+* `VersionedJelphaBot#undo()` -- Restores the previous JelphaBot state from its history.
+* `VersionedJelphaBot#redo()` -- Restores a previously undone JelphaBot state from its history.
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+These operations are exposed in the `Model` interface as `Model#commitJelphaBot()`, `Model#undoJelphaBot()` and `Model#redoJelphaBot()` respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
+Step 1. The user launches the application for the first time.
+The `VersionedJelphaBot` will be initialized with the initial JelphaBot state, and the `currentStatePointer` pointing to that single JelphaBot state.
+.Initial state of JelphaBot
image::UndoRedoState0.png[]
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+Step 2. The user executes _delete 5_ command to delete the 5th task in JelphaBot.
+The *_delete_* command calls `Model#commitJelphaBot()`, causing the modified state of JelphaBot after the `delete 5` command executes to be saved in the `jelphaBotStateList`, and the `currentStatePointer` is shifted to the newly inserted JelphaBot state.
+.State of JelphaBot after *delete 5*
image::UndoRedoState1.png[]
-Step 3. The user executes `add n/David ...` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+Step 3. The user executes `add d/Assignment ...` to add a new task.
+The *_add_* command also calls `Model#commitJelphaBot()`, causing another modified JelphaBot state to be saved into the `jelphaBotStateList`.
+.State of JelphaBot after "add d/Assignment"
image::UndoRedoState2.png[]
[NOTE]
-If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
+If a command fails its execution, it will not call `Model#commitJelphaBot()`, so JelphaBot state will not be saved into the `jelphaBotStateList`.
-Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state.
+Step 4. The user now decides that adding the task was a mistake, and decides to undo that action by executing the `undo` command.
+The `undo` command will call `Model#undoJelphaBot()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous JelphaBot state, and restores JelphaBot to that state.
+.State of JelphaBot after "undo"
image::UndoRedoState3.png[]
[NOTE]
-If the `currentStatePointer` is at index 0, pointing to the initial address book state, then there are no previous address book states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo.
+If the `currentStatePointer` is at index 0, pointing to the initial JelphaBot state, then there are no previous JelphaBot states to restore.
+The `undo` command uses `Model#canUndoJelphaBot()` to check if this is the case.
+If so, it will return an error to the user rather than attempting to perform the undo.
The following sequence diagram shows how the undo operation works:
+.The sequence diagram of the undo feature.
image::UndoSequenceDiagram.png[]
-NOTE: The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
-
-The `redo` command does the opposite -- it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.
+The `redo` command does the opposite -- it calls `Model#redoJelphaBot()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores JelphaBot to that state.
[NOTE]
-If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone address book states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
+If the `currentStatePointer` is at index `jelphaBotStateList.size() - 1`, pointing to the latest JelphaBot state, then there are no undone JelphaBot states to restore.
+The `redo` command uses `Model#canRedoJelphaBot()` to check if this is the case.
+If so, it will return an error to the user rather than attempting to perform the redo.
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+Step 5. The user then decides to execute the command *_list_*.
+Commands that do not modify JelphaBot, such as *_list_*, will usually not call `Model#commitJelphaBot()`, `Model#undoJelphaBot()` or `Model#redoJelphaBot()`.
+Thus, the `jelphaBotStateList` remains unchanged.
+.State of JelphaBot after "list"
image::UndoRedoState4.png[]
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book 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.
+Step 6. The user executes `clear`, which calls `Model#commitJelphaBot()`.
+Since the `currentStatePointer` is not pointing at the end of the `jelphaBotStateList`, all JelphaBot states after the `currentStatePointer` will be purged.
+We designed it this way because it no longer makes sense to redo the `add n/Assignment ...` command.
+This is the behavior that most modern desktop applications follow.
+.State of JelphaBot after "clear"
image::UndoRedoState5.png[]
The following activity diagram summarizes what happens when a user executes a new command:
+.Activity diagram showing details of command execution
image::CommitActivityDiagram.png[]
+<<<
+
==== Design Considerations
===== Aspect: How undo & redo executes
-* **Alternative 1 (current choice):** Saves the entire address book.
+* **Alternative 1:** Saves the entire JelphaBot.
** Pros: Easy to implement.
** Cons: May have performance issues in terms of memory usage.
* **Alternative 2:** Individual command knows how to undo/redo by itself.
-** Pros: Will use less memory (e.g. for `delete`, just save the person being deleted).
+** Pros: Will use less memory (e.g. for _delete, just save the task being deleted).
** Cons: We must ensure that the implementation of each individual command are correct.
-===== Aspect: Data structure to support the undo/redo commands
-
-* **Alternative 1 (current choice):** Use a list to store the history of address book states.
-** Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project.
-** Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both `HistoryManager` and `VersionedAddressBook`.
-* **Alternative 2:** Use `HistoryManager` for undo/redo
-** Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase.
-** Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as `HistoryManager` now needs to do two different things.
// end::undoredo[]
-// tag::dataencryption[]
-=== [Proposed] Data Encryption
-
-_{Explain here how the data encryption feature will be implemented}_
-
-// end::dataencryption[]
-
+<<<
=== Logging
-We are using `java.util.logging` package for logging. The `LogsCenter` class is used to manage the logging levels and logging destinations.
+We are using `java.util.logging` package for logging.
+The `LogsCenter` class is used to manage the logging levels and logging destinations.
* The logging level can be controlled using the `logLevel` setting in the configuration file (See <>)
* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level
@@ -262,121 +1087,538 @@ We are using `java.util.logging` package for logging. The `LogsCenter` class is
Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: `config.json`).
+<<<
+
== Documentation
-Refer to the guide <>.
+Refer to the guide link:{repoURL}/blob/master/docs/Documentation.adoc[here].
+
+<<<
== Testing
-Refer to the guide <>.
+Refer to the guide link:{repoURL}/blob/master/docs/Testing.adoc[here].
+
+<<<
== Dev Ops
-Refer to the guide <>.
+Refer to the guide link:{repoURL}/blob/master/docs/DevOps.adoc[here].
+
+<<<
[appendix]
== Product Scope
*Target user profile*:
-* has a need to manage a significant number of contacts
-* prefer desktop apps over other types
-* can type fast
-* prefers typing over mouse input
-* is reasonably comfortable using CLI apps
+* NUS students who need to manage a large number of tasks
+* Prefers using a desktop app over other types
+* Wants to distinguish at first glance important and unimportant tasks
+* Can type fast; prefers typing over mouse input
+* Is reasonably comfortable using CLI (Command Line Interface) applications
-*Value proposition*: manage contacts faster than a typical mouse/GUI driven app
+*Value proposition*: Using this application will increase the user's efficiency in managing tasks than when using a typical mouse/GUI driven application.
+The visual representation of tasks in the UI will also allow the user to look through entire lists of tasks more quickly than in the terminal.
+<<<
[appendix]
== User Stories
Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (unlikely to have) - `*`
-[width="59%",cols="22%,<23%,<25%,<30%",options="header",]
+[width="100%",cols="12%,<23%,<25%,<30%",options="header",]
|=======================================================================
|Priority |As a ... |I want to ... |So that I can...
-|`* * *` |new user |see usage instructions |refer to instructions when I forget how to use the App
+|`* * *` |organised student |be able to have a visual overarching view of my events and deadlines in a calendar. |
-|`* * *` |user |add a new person |
+|`* * *` |visual student |be able to see my tasks due for specific days in a week or month |easily plan my schedule.
-|`* * *` |user |delete a person |remove entries that I no longer need
+|`* * *` |student with good work-life balance |view tasks with different tags (e.g. health, work) easily |
-|`* * *` |user |find a person by name |locate details of persons without having to go through the entire list
+|`* * *` |goal-oriented student |set goals for the next day |commit myself to what I want to achieve.
-|`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident
+|`* * *` |student |track tasks I've completed in a log | better understand myself and time management.
-|`*` |user with many persons in the address book |sort persons by name |locate a person easily
-|=======================================================================
+|`* * *` |student with a flexible schedule |reschedule my tasks easily |
-_{More to be added}_
+|`* * *` |student taking multiple modules |**_tag_** my tasks |manage the time spent on each module.
+
+|`* * *` |student with a flexible schedule |**_remove tasks_** when they are no longer relevant |
+
+|`* * *` |student who gets tasks done frequently |marks my tasks as completed |focus on the unfinished ones.
+
+|`* * *` |student who does not stay on campus |which of my classes does not have graded attendance |minimise travelling time.
+
+|`* * *` |busy student |what tasks are important at first glance |manage my time well.
+
+|`* * *` |student who loves to procrastinate | get reminders of tasks I have delayed | don't forget to complete them.
+
+|`* * *` |hall resident |keep track of my events and commitments | plan my time properly.
+
+|`* * *` |busy student |track the amount of time spent on each task | plan my schedule effectively.
+
+|`* * *` |goal-oriented student |keep track of my progress in a day | be motivated to be more productive.
+
+|`* *` |student |keep track of number of tasks completed and the number of tasks I have to complete by a certain date/time |
+
+|`* *` |student who actively keeps track of upcoming tasks |view tasks specifically for a range of date/time |
+
+|`* *` |visual student |customize my tags |
+
+|`* *` |student that is driven by motivation |receive timely compliments | stay motivated to complete my tasks on time.
+
+|`* *` |forgetful student |reminders for exam dates | plan my revision efficiently.
+
+|`* *` |unmotivated student |bot that does a morning call for me | wake up and start my day on time.
+
+|`* *` |free-spirited student |set deadlines for doing tutorials and watching webcasts | do things at my own pace while not lagging behind in class.
+
+|`* *` |who needs validation and reminders |debriefed on my achievements (task completed, migrated, scheduled) for that day and what is in store for me the next day |
+
+|`*` |student with many group projects |be able to import and export shared text files |
+
+|`*` |irresponsible student |motivated to complete my tasks |actually complete my tasks in time.
+
+|`*` |user who doesn't always open the computer to run a jar file in the morning |have a convenient way to enter and receive notifications |
+
+|`*` |irresponsible student |criticised |learn from my mistakes and be more responsible in the future.
+
+|`*` |talented student |know which hackathons I already participated in | polish my portfolio.
+
+|`*` |student |track my habits| know if I have strayed from my goal.
+|=======================================================================
+<<<
[appendix]
== Use Cases
-(For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise)
+(For all use cases below, the *System* is the `JelphaBot` and the *Actor* is the `user`, unless specified otherwise)
-[discrete]
-=== Use case: Delete person
+.Use case diagram for the below use cases
+image::UseCaseDiagram.png[]
+
+<<<
+//[discrete]
+=== Use case: UC1 - Add Task
*MSS*
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
+1. User keys in command to add task.
+2. JelphaBot adds the task and displays the added task to the user.
+
Use case ends.
*Extensions*
[none]
-* 2a. The list is empty.
+* 1a.
+JelphaBot detects an error in the entered command.
++
+[none]
+** 1a1. JelphaBot detects error and displays the correct input format to be expected.
+** 1a2. User enters new command.
+** Steps 1a1-1a2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+=== Use case: UC2 - List Tasks
+
+*MSS*
+
+1. User keys in command to list tasks.
+2. JelphaBot displays the list of all the tasks.
+
Use case ends.
-* 3a. The given index is invalid.
+*Extensions*
+
+[none]
+* 1a.
+JelphaBot detects an error in the entered command.
+
[none]
-** 3a1. AddressBook shows an error message.
+** 1a1. JelphaBot detects error and displays the correct input format to be expected.
+** 1a2. User enters new command.
+** Steps 1a1-1a2 are repeated until the command entered is correct.
+
-Use case resumes at step 2.
+Use case resumes from step 2.
-_{More to be added}_
+[none]
+* 1b.
+User specifies a category grouping for the list.
++
+[none]
+** 1b1. JelphaBot will switch to a list that matches the given category.
++
+Use case resumes from step 2.
+
+<<<
+
+=== Use case: UC3 - Mark Task as Done
+
+*MSS*
+
+1. User specifies to mark a task as done by specifying the task index.
+2. JelphaBot updates the task status and displays the updated task to the user.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+JelphaBot detects an error in the entered command.
++
+[none]
+** 1a1. JelphaBot detects error and displays the correct input format to be expected.
+** 1a2. User enters new command.
+** Steps 1a1-1a2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+* 1b.
+JelphaBot detects that the specified task does not exist.
++
+[none]
+** 1b1. JelphaBot detects error and displays the correct input format to be expected.
+** 1b2. User enters new task index to be marked as done.
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+* 1c.
+JelphaBot detects that the specified task has a running time.
++
+[none]
+** 1c1. JelphaBot displays that the task cannot be marked as done due to a running timer.
++
+Use case resumes from step 2.
+
+<<<
+
+=== Use case: UC4 - Edit Task Details
+
+*MSS*
+
+1. User requests to edit a task by specifying the task index and the field(s) they want to edit.
+
+2. JelphaBot edits the specified task in the task list with the specified details.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+JelphaBot detects that the specified task does not exist.
++
+[none]
+** 1a1. JelphaBot detects error and displays the correct input format to be expected.
+** 1a2. User enters new task index to be marked as done.
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2
+
+[none]
+* 1b.
+JelphaBot detects an error in the entered command.
++
+[none]
+** 1b1. JelphaBot detects error and displays the correct input format to be expected.
++
+1b2. User enters new command.
+
+[none]
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+//=== Use case: UC5 - Find Task(s) by Keyword(s)
+//*MSS*
+//
+//1. User requests to find task(s) by entering specified keyword(s).
+//2. JelphaBot shows a list of task(s) that contain the specified keyword(s).
+//+
+//Use case ends.
+//
+//*Extensions*
+//
+//[none]
+//* 1a1. None of the tasks in the task list contain the specified keywords.
+//[none]
+//+
+//** Use case ends.
+
+<<<
+
+=== Use case: UC5 - Delete Task
+
+*MSS*
+
+1. User requests to delete a specific task in the list by specified index.
+2. JelphaBot deletes the task.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+The list is empty.
+[none]
+** 1a1. JelphaBot displays to user that the task list is empty.
++
+Use case ends.
+
+* 1b.
+JelphaBot detects that the specified task does not exist.
++
+[none]
+** 1b1. JelphaBot detects error and displays the correct input format to be expected.
+** 1b2. User enters new task index to be marked as done.
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2
+
+//=== Use case: UC7 - Clear all Tasks
+//*MSS*
+//
+//1. User enters command to clear all tasks.
+//2. JelphaBot removes all listed tasks and returns an empty list.
+//+
+//Use case ends.
+
+<<<
+
+=== Use case: UC6 - Add Reminder
+
+*MSS*
+
+1. User enters reminder for tasks for which he wants to be reminded.
+2. JelphaBot adds a reminder and displays the result to the user +
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+The list is empty.
+
+[none]
+** 1a1. JelphaBot displays to user that the task list is empty.
+Use case ends.
+
+[none]
+* 1b.
+JelphaBot detects that the task the reminder is associated to does not exist.
+[none]
++
+** 1b1 JelphaBot detects error and displays the correct input format to be expected.
+** 1b2. User enters new task index to be add reminder to.
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2
+
+[none]
+* 1c.
+JelphaBot detects an error in the entered command.
++
+[none]
+** 1c1. JelphaBot detects error and displays the correct input format to be expected.
++
+1c2. User enters new command.
+
+[none]
+** Steps 1c1-1c2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+<<<
+
+=== Use case: UC7 - Delete Reminder
+
+*MSS*
+
+1. User requests to delete a reminder for a task in the list by specified index.
+2. JelphaBot deletes the reminder.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+The list is empty.
+[none]
++
+** 1a1. JelphaBot displays to user that there are no reminders.
++
+Use case ends.
+
+* 1b.
+JelphaBot detects that the specified task does not exist.
++
+[none]
+** 1b1. JelphaBot detects error and displays the correct input format to be expected.
+** 1b2. User enters new task index to delete a reminder.
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2
+
+[none]
+* 1c.
+JelphaBot detects an error in the entered command.
++
+[none]
+** 1c1. JelphaBot detects error and displays the correct input format to be expected.
++
+1c2. User enters new command.
+
+[none]
+** Steps 1c1-1c2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+<<<
+// tag::timerUseCase[]
+=== Use Case: UC8 - Start Timer
+
+*MSS*
+
+1. User enters command to start timer for task to be timed.
+2. JelphaBot displays successful execution to user.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+The list is empty.
+[none]
++
+** 1a1. JelphaBot displays to user that the task list is empty.
++
+Use case ends.
+
+[none]
+* 1b.
+JelphaBot detects the task has been mark as completed.
+[none]
++
+** 1b1. JelphaBot displays to user that the task has been marked as completed.
++
+Use case ends.
+
+* 1c.
+JelphaBot detects that the specified task does not exist.
++
+[none]
+** 1c1. JelphaBot detects error and displays the correct input format to be expected.
+** 1c2. User enters new task index to start timing.
+** Steps 1c1-1c2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+<<<
+
+=== Use Case: UC9 - Stop Timer
+
+*MSS*
+
+1. User enters command to stop timer for task being timed.
+2. JelphaBot returns total time spent on that task and stores the information.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+The list is empty.
+[none]
++
+** 1a1. JelphaBot displays to user that the task list is empty.
++
+Use case ends.
+
+[none]
+* 1b.
+JelphaBot detects the task does not have a running timer.
+[none]
++
+** 1b1. JelphaBot displays to user that the task does not have a running timer.
++
+Use case ends.
+
+* 1c.
+JelphaBot detects that the specified task does not exist.
++
+[none]
+** 1c1. JelphaBot detects error and displays the correct input format to be expected.
+** 1c2. User enters new task index to stop timing.
+** Steps 1b1-1b2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+// end::timerUseCase[]
+<<<
+
+=== Use case: UC10 - Navigate to a different date on calendar
+
+*MSS*
+
+1. User specifies date to jump to a specific month and year.
+2. JelphaBot displays updated calendar view with the corresponding tasks due on specified date.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 1a.
+JelphaBot detects an error in the entered command.
++
+[none]
+** 1a1. JelphaBot detects error in specified date and displays the correct input format to be expected.
+** 1a2. User enters new command.
+** Steps 1a1-1a2 are repeated until the command entered is correct.
++
+Use case resumes from step 2.
+
+<<<
[appendix]
== Non Functional Requirements
-. Should work on any <> as long as it has Java `11` or above installed.
-. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
-. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
+. Should work on any <> as long as it has Java `11` or above installed.
+. Should work on both 32-bit and 64-bit machines.
+. Should be able to hold up to 1000 tasks without a noticeable sluggishness in performance for typical usage.
+. Should be able to handle any kind of input, including invalid ones.
+. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
_{More to be added}_
[appendix]
+// tag::glossary[]
== Glossary
-[[mainstream-os]] Mainstream OS::
+[[mainstream-os]]
+Mainstream OS::
Windows, Linux, Unix, OS-X
-[[private-contact-detail]] Private contact detail::
-A contact detail that is not meant to be shared with others
+[[graphical-user-interface]]
+GUI (Graphical User Interface)::
+A type of user interface that allows for interaction between the user and electronic devices through graphical icons
-[appendix]
-== Product Survey
-
-*Product Name*
-
-Author: ...
-
-Pros:
+[[command-line-interface]]
+CLI (Command Line Interface)::
+A type of user interface that allows for interaction between the user and electronic devices in the form of lines of text.
-* ...
-* ...
+// end::glossary[]
-Cons:
-
-* ...
-* ...
+<<<
[appendix]
== Instructions for Manual Testing
@@ -384,7 +1626,8 @@ Cons:
Given below are instructions to test the app manually.
[NOTE]
-These instructions only provide a starting point for testers to work on; testers are expected to do more _exploratory_ testing.
+These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. +
+For this section, `markdown` will be used to denote commands that can be entered into JelphaBot.
=== Launch and Shutdown
@@ -392,7 +1635,7 @@ These instructions only provide a starting point for testers to work on; testers
.. Download the jar file and copy into an empty folder
.. Double-click the jar file +
- Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
+ Expected: Shows the GUI with a set of sample tasks. The window size may not be optimum.
. Saving window preferences
@@ -400,26 +1643,235 @@ These instructions only provide a starting point for testers to work on; testers
.. Re-launch the app by double-clicking the jar file. +
Expected: The most recent window size and location is retained.
-_{ more test cases ... }_
-
-=== Deleting a person
+=== Changing Tabs
+
+. Summary
+.. Switch to Summary with *_:s_*, *_:S_* or *_summary_*. +
+.. Switch to Summary with *_:s_*, *_:S_* or *_summary_*. +
+Expected: Success message is shown in the Results Display.
+
+. Task List
+.. Switch to Task List with *_:t_*, *_:T_* or *_list_*. +
+Expected: Success message is shown in the Results Display.
+
+. Calendar
+.. Switch to Calendar with *_:c_*, *_:C_* or *_calendar_*. +
+Expected: Success message is shown in the Results Display.
+
+. Productivity
+.. Switch to Productivity with *_:p_*, *_:P_* or *_productivity_*. +
+Expected: Success message is shown in the Results Display.
+
+. Reminder
+.. Switch to Reminder with *_:r_*, *_:R_* or *_remindertab_*. +
+Expected: Success message is shown in the Results Display.
+
+=== Adding a Task
+
+. Adding a new task to a cleared list
+.. Prerequisites: Clear the list with the *_clear_* command.
+.. For all test cases that successfully add a task, the respective total for each category should increment as new tasks are added.
+.. Test case: _add d/test dt/Apr-06-2020 23 59 m/CS2103t_ +
+Expected: A new task is added with the description "test", and a module code of "CS2103T".
+.. Test case: _add d/test2 dt/Apr-06-2020 23 59 p/1 m/CS2103t_ +
+Expected: A new task is added with the description "test2", a module code of "CS2103T", and both the module code and descripton should be bolded.
+.. Test case: _add d/test3 dt/Apr-06-2020 23 59 p/-1 m/CS2103t_ +
+Expected: A new task is added with the description "test3", a module code of "CS2103T", and both the module code and descripton should be in italics.
+. Adding a task with incomplete parameters
+.. Test case: _add d/aa_ +
+Expected: No task is added.
+Error details shown in the results message. +
+.. Other incorrect add commands to try: other parameters are missing. +
+Expected: Similar to previous.
+. Adding a task with incorrect parameters
+.. Test case: _add d/aa dt/Joon-06-2020 23 59 p/-1 m/CS2103t_ +
+Expected: No task is added.
+Error message with correct format of date command. +
+.. Other incorrect add commands to try: other parameters are wrongly formatted. +
+Eg. non-alphanumeric characters in description or tag, invalid priority, module codes not complying to NUS format (2-3 Alphabets, 4 numbers, one optional letter) +
+Expected: Similar to previous.
+
+=== Editing a Task
+
+. Editing a task that was previously added
+.. Prerequisites: Execute the *_add_* commands in the previous section.
+.. Edit each field as per examples given in *_edit_* command section.
+
+=== Completing a Task
+
+. Setting an existing task to Complete.
+.. Prerequisites: Execute the *_add_* commands in the previous section.
+.. Complete tasks as per examples given in *_done_* command section.
+
+=== Changing the list category
+
+. Displaying tasks by a different category
+.. Prerequisites: Execute the *_add_* commands above.
+.. Test case: *_list module_*, followed by _add d/test dt/Apr-06-2020 23 59 m/3230_ +
+Expected: A new module category should appear with a category title of "CS3230".
+.. Test case: *_list date_*, followed by _add d/test dt/TOMORROW 23 59 m/3230_, where *_TOMORROW_* refers to the date of the next day. +
+Expected: A new task should appear under the category header "Due This Week".
+.. Test case: *_list invalid_* +
+Expected: List display does not change.
+Error details shown in the results message.
+Status bar remains the same.
+
+=== Deleting a Task
+
+. Deleting a task while all tasks are listed
+
+.. Prerequisites: List all tasks using the *_list_* command. Multiple tasks in the list.
+.. Test case: _delete 1_ +
+Expected: First task is deleted from the list.
+Details of the deleted task are shown in the results message.
+.. Test case: _delete 0_ +
+Expected: No task is deleted.
+Error details are shown in the results message.
+.. Other incorrect delete commands to try: *_delete_*, *_delete x_* (where x is larger than the list size) +
+Expected: Similar to previous.
+
+=== Progress Bar visualisation
+
+. Marking a task that was previously added as complete
+
+.. Prerequisites: Execute the *_add_* commands in the <>.
+.. Complete tasks as per examples given in done command section. +
+Expected: Upon successful completion of a task, if that task is due by the end of the day, progress bar in productivity tab is updated and displayed total number of completed tasks is updated.
+
+=== View Tasks with Running Timers
+
+. Start timer for a task that was previously added
+
+.. Prerequisites: Execute the *_add_* commands in the <>. Task must not be marked as completed.
+.. Test case: _start 1_ +
+Expected: Starts timing first task from the list.
+Details of the timing task is shown in the results message. +
+Task being timed is displayed under Running Timer(s) in productivity tab.
+.. Test case: _start 0_ +
+Expected: No timer started.
+Error details shown in the results message.
+.. Other incorrect start commands to try: *_start_*, *_start x_* (where x is larger than the list size or is index of task already marked completed) +
+Expected: Similar to previous.
+
+=== View Time Spent on Tasks
+
+. Stop timer for a task that was previously added
+
+.. Prerequisites: Execute the *_start_* commands in the <>.
+.. Test case: _stop 1_ +
+Expected: Stops timing first task from the list.
+Details of the timed task is shown in the results message. +
+Displayed time spent is updated in productivity tab. +
+Task timed is removed from Running Timer(s) displayed in productivity tab.
+.. Test case: _stop 0_ +
+Expected: No timer stopped.
+Error details shown in the results message.
+.. Other incorrect stop commands to try: *_stop_*, *_stop x_* (where x is larger than the list size or is index of task without running timer) +
+Expected: Similar to previous.
+
+=== View Tasks due on a specific Date
+
+. Input a date belonging to the current calendar month to view tasks due
+.. Prerequisites: Navigate to the calendar with the *_calendar_* command (or other variants as listed above).
+.. Test case: _calendar Apr-20-2020_ +
+Expected: Task(s) due on the input date will be displayed with results message displaying the number of tasks listed.
+If there are no tasks due on the input date, no tasks would be displayed.
+The input date would also be highlighted on the calendar.
+.. Test case: _calendar Apri-20-2020_ +
+Expected: Error message due to the invalid format for the input date would be displayed in the results message.
+
+. Input a date not belonging to the current calendar month to view tasks due
+.. Prerequisites: Navigate to the calendar with the *_calendar_* command (or other variants as listed above).
+.. Test case: _calendar Oct-20-2020_ +
+Expected: Task(s) due on the input date will be displayed with results message displaying the number of tasks listed.
+If there are no tasks due on the input date, no tasks would be displayed.
+.. Test case: _calendar Joon-20-2020_ +
+Expected: Expected: Error message due to the invalid format for the input date would be displayed in the results message.
+
+=== Navigating the Calendar
+
+. Navigate to Today's Date on Calendar
+.. Prerequisites: Navigate to the calendar with the *_calendar_* command (or other variants as listed above).
+.. Test case: *_calendar today_* +
+Expected: Calendar will change to be the current month and year, with today's date also highlighted.
+Task(s) due today will be displayed with results message displaying the number of tasks listed.
+If there are no tasks due today, no tasks would be displayed.
+
+. Navigate to different month and year on Calendar
+.. Prerequisites: Navigate to the calendar with the *_calendar_* command (or other variants as listed above).
+.. Test case: _calendar May-2020_ +
+Expected: Calendar will change to be for May 2020, with the first day of the May highlighted.
+Task(s) due on the first day of May will be displayed with results message displaying the number of tasks listed.
+If there are no tasks due, no tasks would be displayed.
+.. Test case: _calendar may-2020_ +
+Expected: Error message due to the invalid format for the input month and year would be displayed in the results message.
+
+=== Reminder Feature
+
+. Adding a reminder to remind a task
+.. Prerequisites: List all tasks using the *_list_* command to have a full view of the tasks.
+Select the `INDEX` of the task that needs to be reminded.
+.. Test case: _reminder 2 days/2 hours/2_ +
+Expected: A reminder which is associated to the *_Task_* at index 2 will be added.
+.. Test case: _reminder -1 days/1 hours/0_ +
+Expected: Error message due to negative index.
+.. Test case: _reminder 1 days/30 hours/0_ +
+Expected: Error due to invalid day count, which has a limit of 7.
+.. Test case: _reminder 1 days/1 hours/30_ +
+Expected: Error due to invalid hour count, which can be converted to days if it exceeds 24.
+.. Other invalid commands to try: *_reminder _*, _reminder 100000 days/1 hours/1_
+
+. Removing a reminder
+.. Prerequisites: List all tasks using the *_list_* command, and look for the task that is associated to the reminder that needs to be deleted.
+.. Test case: _delrem 1_ +
+Expected: The reminder for task at index 1 will be removed, if it exists.
+.. Other incorrect commands to try: *_delrem_* , *_delrem x_* (where x is larger than the list size)
+
+=== Data Storage
+
+. Missing data files
+
+.. Open the `/data/` folder and delete all .json files in that folder.
+.. Launch JelphaBot by double-clicking the jar file. +
+Expected Outcome: JelphaBot starts up with sample data in the GUI.
+Sample data should be configured such that there are dates due within the current day and week.
+
+. Corrupted data files
+
+.. Open the `/data/` folder and delete all .json files in that folder.
+.. Launch JelphaBot by double-clicking the jar file. +
+Expected Outcome: JelphaBot starts up with sample data in the GUI.
+Sample data should be configured such that there are dates due within the current day and week.
+
+<<<
+[appendix]
+== Effort
-. Deleting a person while all persons are listed
+The following section describes the effort we have put into this project.
-.. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
-.. Test case: `delete 1` +
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
-.. Test case: `delete 0` +
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
-.. Other incorrect delete commands to try: `delete`, `delete x` (where x is larger than the list size) _{give more}_ +
- Expected: Similar to previous.
+=== Use of VCS and CI tools
-_{ more test cases ... }_
+For all of our members, this was the first time we had to manage a repositiory with over 10,000 lines of code.
+Additionally, this was the *first time many of our team members were introduced* to version control tools like Git and Github, as well as CI tools like Travis and AppVeyor.
+The lack of familliarity with the tools used meant that *a lot of effort was spent at the start of the project setting things up and ensuring that the changes to the codebase were as intended*.
+The project was the *most difficult to manage thus far* out of all our previous module projects or submissions due to the large number of tools and standards required.
+However, as each of our team members got more used to the tools we were using, we were able to *implement required checks and branch protection which greatly improved the quality of code committed*.
-=== Saving data
+=== Maintaining good software design while implementing Object-Oriented paradigms
-. Dealing with missing/corrupted data files
+Each of our features required us to have a *complete understanding and thorough analysis of the preexisting architectural components* which came with the AB3 codebase.
+In implementing our features across the codebase, all team members would use the preexisting classes and methods in different ways.
+*Hence, care had to be taken to make any modifications that would not invalidate the work of another teammate*.
+Simultaneously, we had to ensure good software design, such as ensuring that DRY and SRP are not violated and maintaining a high level of abstraction while reducing unneeded functions.
+All this required conscious effort, such as *organising regular team meetings to update our teammates on our latest implementations*, as well as *reducing unprotected access to code variables through interfaces and class inheritance*.
+We are proud that we managed to *implement each tab in a clean, concise manner that ensures these principles are followed as far as possible*.
-.. _{explain how to simulate a missing/corrupted file and the expected behavior}_
+=== Real-time synchronization and integration between GUI and internal logic components
-_{ more test cases ... }_
+AB3 uses an observer design pattern where a `UniqueTaskList` allows changes to it to be observed by a `Listener` observing that list.
+This implementation was *challenging as it required constant updates to be accounted for in real-time* whenever another command edited the main task list.
+In addition, since multiple tabs retrieved information from the same underlying task list, it had to be sensitive to command inputs from inactive tabs.
+For instance, when a user deletes a `Task`, its corresponding `Reminder` should also be removed, even if the Reminder tab is not currently active in the UI.
+This required us to *write tests for `Model` and `Logic` classes as well as minimise dependencies between the `Ui` and other components*.
+It *required a lot more effort as we had more tabs, and thus more object properties to keep track of*, than the initial AB3 project.
+In the end, our group managed to achieve a high level of testing for most `Model` components and *achieve responsive UI feedback for all CLI-entered commands*.
diff --git a/docs/Documentation.adoc b/docs/Documentation.adoc
index ad90ac87bda..1f12616efb8 100644
--- a/docs/Documentation.adoc
+++ b/docs/Documentation.adoc
@@ -1,4 +1,4 @@
-= AddressBook Level 3 - Documentation
+= JelphaBot - Documentation
:site-section: DeveloperGuide
:toc:
:toc-title:
@@ -14,6 +14,7 @@ ifdef::env-github[]
endif::[]
:repoURL: https://github.com/se-edu/addressbook-level3/tree/master
+[[Documentation]]
== Introduction
We use asciidoc for writing documentation.
diff --git a/docs/SettingUp.adoc b/docs/SettingUp.adoc
index c0659782fab..1b940342bb2 100644
--- a/docs/SettingUp.adoc
+++ b/docs/SettingUp.adoc
@@ -1,4 +1,4 @@
-= AddressBook Level 3 - Setting Up
+= Jelphabot - Setting Up
:site-section: DeveloperGuide
:toc:
:toc-title:
@@ -37,7 +37,7 @@ Do not disable them. If you have disabled them, go to `File` > `Settings` > `Plu
== Verifying the setup
-. Run the `seedu.address.Main` and try a few commands
+. Run the `seedu.jelphabot.Main` and try a few commands
. <> to ensure they all pass.
== Configurations to do before writing code
diff --git a/docs/Testing.adoc b/docs/Testing.adoc
index 5767b92912c..dfbc3eebea7 100644
--- a/docs/Testing.adoc
+++ b/docs/Testing.adoc
@@ -1,4 +1,4 @@
-= AddressBook Level 3 - Testing
+= JelphaBot - Testing
:site-section: DeveloperGuide
:toc:
:toc-title:
@@ -12,7 +12,7 @@ ifdef::env-github[]
:note-caption: :information_source:
:warning-caption: :warning:
endif::[]
-:repoURL: https://github.com/se-edu/addressbook-level3/tree/master
+:repoURL: https://github.com/AY1920S2-CS2103T-F09-2/main
== Running Tests
@@ -35,11 +35,11 @@ See <> for more info on how to run tests using G
We have three types of tests:
. _Unit tests_ targeting the lowest level methods/classes. +
-e.g. `seedu.address.commons.StringUtilTest`
+e.g. `StringUtilTest`
. _Integration tests_ that are checking the integration of multiple code units (those code units are assumed to be working). +
-e.g. `seedu.address.storage.StorageManagerTest`
+e.g. `StorageManagerTest`
. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together. +
-e.g. `seedu.address.logic.LogicManagerTest`
+e.g. `LogicManagerTest`
== Troubleshooting Testing
diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc
index 4e5d297a19f..51c2214a793 100644
--- a/docs/UserGuide.adoc
+++ b/docs/UserGuide.adoc
@@ -1,177 +1,845 @@
-= AddressBook Level 3 - User Guide
+= JelphaBot - User Guide
:site-section: UserGuide
:toc:
-:toc-title:
-:toc-placement: preamble
+:toc-title: Table of Contents
+:toclevels: 4
+:toc-placement: macro
:sectnums:
:imagesDir: images
:stylesDir: stylesheets
:xrefstyle: full
:experimental:
+:icons: font
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
+:important-caption: :heavy_exclamation_mark:
endif::[]
-:repoURL: https://github.com/se-edu/addressbook-level3
-
-By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT`
+:repoURL: https://github.com/AY1920S2-CS2103T-F09-2/main
+
+[.text-center]
+By: `AY1920S2-CS2103T-F09-2` Since: `Jan 2020` Licence: `MIT` +
+{blank} +
+{blank} +
+A0190055L Ong Eden +
+A0187819J Amanda Lam +
+A0188384M Lim We Si, Jel +
+A0184679H Yap Dian Hao +
+A0187280Y Thng Yao Jie
+
+<<<
+toc::[]
+<<<
== Introduction
-AddressBook Level 3 (AB3) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB3 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy!
+Welcome to JelphaBot! +
+This user guide is written for *new and experienced users of Jelphabot*. This guide will equip you with the basics so that you can quickly enjoy and master the features offered.
+
+If this is not your first time using JelphaBot, you can refer to <> to get started right away!
+
+=== What is JelphaBot?
+
+JelphaBot is *a desktop app for managing tasks* specially designed by and *for NUS students* that allows you to *recognise important tasks at a glance* so that you can prioritise commitments and manage your time.
+
+You can enter commands in JelphaBot through a *Command Line Interface* (CLI), which means that if you can *type quickly*, JelphaBot can help you get work done faster than a traditional mouse-controlled Graphical User Interface (GUI), *while still retaining the benefits of a beautiful user interface*.
+
+[.text-center]
+.Brief overview of the app
+image::ug_figures/Ui.png[width="600"]
+<<<
+
+=== Overview of features
+The main features of JelphaBot are split into five tabs.
+
+* *<>* - Summary of the updates to your task list over the past day.
+* *<>* - View and manage tasks in your task list.
+* *<>* - View your schedule on a specific day or within a specific month.
+* *<>* - Track your overall productivity through metrics such as task completion rate.
+* *<>* - Set and manage your upcoming reminders.
+
+Each tab provides a specific feature aimed to help you manage your tasks and deadlines more productively!
+
+Interested? Jump to the <> to get started. Enjoy!
+
+=== Using this User Guide
+
+This User Guide is filled with information to help you set up and make the best out of you very own JelphaBot!
+You will be able to learn more about the commands that are available for you, together with examples of how they are used.
+These commands are also consolidated in <> for your convenience.
+
+[[hyperlink]]
+==== Notation used in this Guide
+
+To aid in your understanding throughout this User Guide, you may find below the different symbols and formatting used throughout this guide. We have also provided <> to help you navigate between related sections.
+
+.Common symbols used throughout this guide.
+[width="100%",cols="^40%,<60%,options="header",]
+|=======================================================================
+|*Symbol* | *What does it mean?*
+| `command` | Command that can be typed into the command box
+| kbd:[Key] | A Key that you should press on your keyboard
+ifdef::env-github[]
+| :bulb: | Tips and tricks that might be useful
+| :information_source: | Additional information that is good to know
+| :heavy_exclamation_mark: | Important pointers to take note of
+endif::[]
+ifndef::env-github[]
+| image:icons/bulb.png[width=40] | Tips and tricks that might be useful
+| image:icons/note.png[width=40] | Additional information that is good to know
+| image:icons/Important.png[width=40] | Important pointers to note
+endif::[]
+| <> | Link to another section or website
+// also known as TIP, NOTE, IMPORTANT
+|=======================================================================
+
+<<<
== Quick Start
-. Ensure you have Java `11` or above installed in your Computer.
-. Download the latest `addressbook.jar` link:{repoURL}/releases[here].
-. Copy the file to the folder you want to use as the home folder for your Address Book.
-. Double-click the file to start the app. The GUI should appear in a few seconds.
+1. Ensure you have Java `11` or above installed in your Computer.
+2. Download the latest `jelphabot.jar` link:{repoURL}/releases[here].
+3. Copy the file to the folder you want to use as JelphaBot's home folder.
++
+[NOTE]
+This is important because it decides where your information is saved! +
+Ensure that JelphaBot has write permissions to that folder.
+4. Double-click the file to start the app.
+The GUI should appear in a few seconds. +
+JelphaBot should initialize with a sample list of tasks as shown in the following diagram.
++
+Upon running JelphaBot, you will see various components on it's main display screen.
+The components of the main screen is labelled below.
+
-image::Ui.png[width="790"]
+[.text-center]
+.Expected result after running JelphaBot
+image::ug_figures/UiAnnotated.png[]
+
-. Type the command in the command box and press kbd:[Enter] to execute it. +
-e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
-. Some example commands you can try:
+<<<
++
+5. Some tasks should already be present in JelphaBot.
+[NOTE]
+JelphaBot is initialized with a sample list of tasks, to test if you've installed JelphaBot correctly! +
+If you do not see this, please try deleting JelphaBot and its accompanying files and folders and repeat steps 2 to 4.
+6. Type a command in the command box and press kbd:[Enter] to execute it. +
+e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. To start entering your own commands, use `clear` to reset JelphaBot.
+7. Some example commands you can try:
+* `add d/Assignment 1 dt/10-Mar-2020 23 59 m/CS2103T` : +
+adds a task with description "Assignment 1" to the task list.
+* `list` : lists all tasks.
+* `delete 1` : deletes the 1st task shown in the current list.
+* `exit` : exits the app.
++
+[TIP]
+You can use the kbd:[UP] and kbd:[DOWN] keys to view your last entered commands, +
+and kbd:[Ctrl] + kbd:[Tab] to nagivate to the next tab quickly!
-* *`list`* : lists all contacts
-* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book.
-* **`delete`**`3` : deletes the 3rd contact shown in the current list
-* *`exit`* : exits the app
+Refer to <> to learn about how each command can help you. +
+A summarized list of commands is available <>. +
+We hope you have a great time using JelphaBot!
-. Refer to <> for details of each command.
+<<<
-[[Features]]
== Features
-====
-*Command Format*
+In this section, you can find details about the commands that JelphaBot supports.
+These include the function of the command, its format, and example usages.
-* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
-* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
-* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
-* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
-====
+For easier naviagation, this guide will go through features according to the order of tabs shown on the User Interface.
+
+=== Common commands
-=== Viewing help : `help`
+==== Viewing help : `help`
+If you can't recall the command you need, you can enter the `help` command in any panel. +
+A help window will appear with a link to this user guide. +
Format: `help`
-=== Adding a person: `add`
+[.text-center]
+.Expected result after running `help`
+image::ug_figures/help.png[width="600]
-Adds a person to the address book +
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+==== Exiting the program : `exit`
-[TIP]
-A person can have any number of tags (including 0)
+You can exit the program anytime by entering the `exit` command directly from any panel. +
+Format: `exit`
-Examples:
+==== Switching between tabs
+
+You can switch between tabs anytime by pressing kbd:[Ctrl] + kbd:[Tab] on your keyboard to move to the next tab on the right.
+If you are already on the rightmost tab, it wraps around to the leftmost tab.
+You can also move to tabs directly by using the respective shortcut commands.
+These make JelphaBot easier to use for experienced users.
+Easily remember command shortcuts by checking the bolded letter in the title of every panel!
+
+[.text-center]
+.List of applicable Switch Tab commands.
+[width="70%",cols="45%,60%"]
+|===
+|Command |Tab switched to
+
+|`summary`, or `:s`| Summary
+|`list`, or `:t`| Task List
+|`calendar`, or `:c`| Calendar
+|`productivity`, or `:p`|Productivity
+|`remindertab`, or `:r`|Reminder
+|===
+
+<<<
+// tag::summary[]
+=== Summary (Eden)
+
+This will be the first panel you see after entering JelphaBot!
+
+This section gives you a minimalistic overview of the day, namely tasks that you have due within the day, and tasks that you have completed within the day.
+Tasks displayed will only have it's module code as well as their description for simplicity!
+
+==== Viewing the summary tab: `summary`
+
+You can enter the `summary` command or its shortcuts `:S` or `:s` to manually switch to the summary tab.
+Summary panel shows your tasks that are due today, and those that you have completed today.
+Once a task that is due today is marked as done, it will appear under the tasks that you have completed today.
+
+Format: `summary` +
+Shortcut: `:S` or `:s`
+
+[.text-center]
+.Example of expected result after executing `summary`
+image::ug_figures/Ui.png[width="600"]
+
+Summary panel shows the tasks that are Due Today, and Completed Today.
+
+<<<
+
+Once a task under the Due Today header is marked as done, it will appear under the Completed Today tab.
+
+[.text-center]
+.Expected view of the Summary tab after completing the task, ACC1101 Tutorial 4
+image::ug_figures/SummaryViewAfterTaskComplete.png[width="600"]
+
+// end::summary[]
+
+<<<
+// tag::tasklist[]
+=== Task Management (Yao Jie)
+
+JelphaBot allows you to track and manage your tasks comprehensively as well!
+You can view and sort all your tasks from the Task List page. +
+You can enter the `list` command or its shortcuts `:T` or `:t` to instantly switch to the task list tab.
+The task list panel will then display all your tasks sorted into various categories. +
+
+Format: `list` +
+Shortcut: `:T` or `:t`
+
+[.text-center]
+.Example of expected result after executing `list`
+image::ug_figures/TaskListTab.png[width="600"]
+
+<<<
+
+==== Reading the Task List
+
+The task list is formatted so that you can distinguish urgent tasks at first glance.
+The start of every task is labelled with a module code so that you can visually categorize them.
+Tasks are tagged according to their importance:
+
+* Default priority
+* *High Priority* tasks will be *bolded* to denote important tasks.
+* _Low priority_ tasks will be _italicized_ to denote optional tasks.
+
+The start of every task will be labelled with a module code so that you can visually categorize them. +
+Go <<#add, here>> to read more about adding tasks with priority and <<#edit, here>> for editing task priority.
+
+====
+*Command Format for Task list commands*
+
+* Parts of the command in `UPPER_CASE` represent command parameters that have to be supplied by you. +
+e.g. in `add d/DESCRIPTION`, `DESCRIPTION` represents a field where you can provide the appropriate description, such as `add d/Assignment 1`.
+* Parameters in square brackets are optional e.g `d/DESCRIPTION [p/PRIORITY]` can be used as `d/Assignment 1 p/0` or as `d/Assignment 1`.
+* Parameters with a trailing `…` can be used as many times as you want, or can also be omitted. +
+e.g. `[t/TAG]...` can be used once as `t/project`, or multiple times like `t/project t/graded`, and so on.
+* Parameters can be in any order e.g. if the command specifies `d/DESCRIPTION p/PRIORITY`, `p/PRIORITY d/DESCRIPTION` is also acceptable.
+====
+// end::tasklist[]
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+<<<
+// tag::add[]
+[[add]]
+==== Adding a Task: `add`
-=== Listing all persons : `list`
+You can add new tasks to your task list in JelphaBot with the `add` command. This allows you to update your task list with new tasks whenever they arise.
-Shows a list of all persons in the address book. +
-Format: `list`
+Format: `add d/DESCRIPTION dt/DATETIME m/MODULE_CODE [p/PRIORITY] [t/TAG]...`
-=== Editing a person : `edit`
+[.text-center]
+.Example of an expected result after executing `add d/Assignment 1 dt/Jan-01-2020 23 59 m/CS1231 t/graded`
+image::ug_figures/addCommand.png[width="600"]
-Edits an existing person in the address book. +
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
+<<<
****
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index *must be a positive integer* 1, 2, 3, ...
-* At least one of the optional fields must be provided.
-* Existing values will be updated to the input values.
-* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
-* You can remove all the person's tags by typing `t/` without specifying any tags after it.
+* For dt/DATETIME inputs, please use the format MMM-dd-YYYY HH mm. +
+** MMM: the corresponding month in 3 letters.
+** dd: the corresponding day in 2 numbers.
+** YYYY: the corresponding year (AD) as 4 numbers.
+** HH: the hour the task is due, in 24-hour format.
+** mm: the minute the task is due.
+
+* Values that p/PRIORITY can take are -1, 0 or 1.
****
+[IMPORTANT]
+Format of the month in DATETIME (MMM) input has to have the first letter in upper-case. +
+E.g `Mar` instead of `mar` when specifying the month of March.
+
Examples:
-* `edit 1 p/91234567 e/johndoe@example.com` +
-Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
-* `edit 2 n/Betsy Crower t/` +
-Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+* `add d/Assignment 1 dt/Jan-01-2020 23 59 m/CS3230 p/1`
+* `add d/Project TP dt/Jan-01-2020 23 59 m/CS2103T p/1 t/pair t/work`
+
+[TIP]
+A task can have any number of tags (including 0)! +
+If the priority field is not specified, priority is set to Default priority.
+// end::add[]
+
+<<<
+
+// tag::list[]
+==== Listing all Tasks : `list`
+
+JelphaBot allows you to list all your current tasks. In order to make it easier for you to view and use JelphaBot, you can group your tasks by some categories. These categories can be specified through optional arguments.
+Format: `list [GROUPING_CATEGORY]`
+
+****
+* If no `GROUPING_CATEGORY` is provided, the `date` grouping will be applied by default.
+* Valid `GROUPING_CATEGORY` values are `date` (groups tasks by date) and `module` (Groups tasks by module code)
+****
+
+===== Grouping Tasks by Date : `list date`
+
+You can group tasks based on their due date.
+This is also the default interface for the task list tab. +
+Format: `list date`
-=== Locating persons by name: `find`
+[.text-center]
+.Example of an expected result after executing `list date`
+image::ug_figures/listByDate.png[width="600"]
-Finds persons whose names contain any of the given keywords. +
+<<<
+
+`list date` allows you to group your tasks into the following categories:
+
+* *Overdue* +
+(Shows tasks which are past their due date)
+* *Due Today* +
+(Shows tasks not overdue and due by the end of the current day)
+* *Due This Week* +
+(Shows tasks due within the next seven days)
+* *Due Someday* +
+(Shows all other tasks that do not fit into prior categories)
+
+These categories are arranged to make it easier for you to see what is immediately due.
+By moving tasks that are due soon to the top of the list, you can decide what to focus your time on.
+
+===== Grouping Tasks by Module : `list module`
+
+You can also group your tasks based on their module code. +
+Format: `list module` +
+[.text-center]
+.Example of an expected result after executing `list module`
+image::ug_figures/listByModule.png[width="600"]
+
+This grouping allows you to manage your time by tracking the amount of time spent on each module.
+You can also see which modules have upcoming projects or assignments due.
+// end::list[]
+
+<<<
+==== Locating Tasks by name: `find`
+
+You can find tasks in your task list with description containing any of the given keywords. +
Format: `find KEYWORD [MORE_KEYWORDS]`
+[.text-center]
+.Example of an expected result after executing `find tutorial`
+image::ug_figures/findCommand.png[width="600"]
+
****
-* The search is case insensitive. e.g `hans` will match `Hans`
-* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
-* Only the name is searched.
-* Only full words will be matched e.g. `Han` will not match `Hans`
-* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+* The search is case insensitive. e.g `tut` will match `Tut`
+* The order of the keywords does not matter. e.g. `project Work` will match `Work project`
+* Only the description is searched.
+* Only full words will be matched e.g. `Tut` will not match `Tutorial`
+* Tasks matching at least one keyword will be returned (i.e. `OR` search). e.g. `Project Work` will return `Project Group`, `Work meeting`
****
+Examples:
+
+* `find assignment` +
+Returns `Assignment 1` and `assignment task`
+* `find Tutorial Project MidTerm` +
+Returns any task having descriptions of `Tutorial`, `Project`, or `MidTerm`
+
+<<<
+// tag::edit[]
+[[edit]]
+==== Editing a Task : `edit`
+
+If there are changes to existing tasks in JelphaBot, you can edit it with the `edit` command. +
+Format: `edit INDEX [d/DESCRIPTION] [dt/DATETIME] [m/MODULE_CODE] [p/PRIORITY (-1, 0, or 1)] [t/TAG]...`
+
+[.text-center]
+.Example of an expected result after executing `edit 1 m/CS2105 d/Tutorial 2`
+image::ug_figures/editCommand.png[width="500"]
+****
+* Edits the task at the specified `INDEX` number shown in the displayed task list.
+* The index provided *must be positive* and the task to edit cannot have a running timer.
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values. +
+When tags are edited, all existing tags will be removed and replaced with the new tags.
+****
Examples:
-* `find John` +
-Returns `john` and `John Doe`
-* `find Betsy Tim John` +
-Returns any person having names `Betsy`, `Tim`, or `John`
+* `edit 1 m/CS2105 d/Tutorial 2` +
+Edits the Module Code of the first task to `CS2105` and Description to `Tutorial 2`.
+* `edit 2 dt/Jan-2-2020 23 59 t/` +
+Edits the Date and Time of the second task to be `Jan-2-2020 23 59` and clears all existing tags.
++
+[TIP]
+You can remove all the task's tags by typing `t/` without specifying any tags after it.
+// end::edit[]
+
+<<<
+
+==== Completing a Task : `done`
+When you complete a task, you can mark it as done in JelphaBot. The task's status will automatically be updated in the display. +
+Format: `done INDEX`
+
+[.text-center]
+.Example of an expected result after executing `done 1`
+image::ug_figures/doneCommand.png[width="600"]
+
+****
+* Marks the task at the specified `INDEX` as done.
+* The index refers to the index number shown in the displayed task list.
+* The index *must be a positive integer* 1, 2, 3, ...
+* The task must not have a running timer.
+****
+
+<<<
+==== Deleting a Task : `delete`
// tag::delete[]
-=== Deleting a person : `delete`
-Deletes the specified person from the address book. +
+If you no longer need a task stored in JelphaBot, you can delete it with the `delete` command.
+
Format: `delete INDEX`
+[.text-center]
+.Example of an expected result after executing `delete 1`
+image::ug_figures/deleteCommand.png[width="600"]
+
****
-* Deletes the person at the specified `INDEX`.
-* The index refers to the index number shown in the displayed person list.
+* Deletes the task at the specified `INDEX`.
+* The index refers to the index number shown in the displayed task list.
* The index *must be a positive integer* 1, 2, 3, ...
+* Deleting a task deletes any reminders for it too.
****
Examples:
* `list` +
`delete 2` +
-Deletes the 2nd person in the address book.
+Deletes the 2nd task in the task list.
* `find Betsy` +
`delete 1` +
-Deletes the 1st person in the results of the `find` command.
-
+Deletes the 1st task in the results of the `find` command.
// end::delete[]
-=== Clearing all entries : `clear`
-Clears all entries from the address book. +
+<<<
+==== Clearing all Tasks : `clear`
+
+If you want to reset JelphaBot and start over, you can use the `clear` command.
+This command will delete all existing Tasks and Reminders from JelphaBot.
+
Format: `clear`
-=== Exiting the program : `exit`
+[.text-center]
+.Example of an expected result after executing `clear`
+image::ug_figures/clearCommand.png[width="600"]
-Exits the program. +
-Format: `exit`
+<<<
+// tag::showcompleted[]
+==== Showing completed Tasks : `show-completed` (Eden)
-=== Saving the data
+You can keep a log of all the tasks that have been completed with the `show-completed` command.
-Address book data are saved in the hard disk automatically after any command that changes the data. +
-There is no need to save manually.
+[.text-center]
+.Example of an expected result after executing `show-completed`
+image::ug_figures/showCompletedCommand.png[width="600"]
+
+The figure above shows a task list with a single task completed.
+
+<<<
+
+If you do not have any currently complete tasks, the displayed list will be empty and a message will be shown telling you that you currently do not have any completed tasks!
+
+[.text-center]
+.Example of an expected result after executing `show-completed`, if the task list does not have any completed tasks
+image::ug_figures/showCompletedCommandNoCompleted.png[width="600"]
+// end::showcompleted[]
+
+The corresponding message is shown in the Results Display.
+
+<<<
+// tag::showincomplete[]
+==== Showing incomplete Tasks: `show-incomplete` (Eden)
+
+You can display all the tasks in your task list that are currently incomplete, so that you can see what you should do next.
-// tag::dataencryption[]
-=== Encrypting data files `[coming in v2.0]`
+[.text-center]
+.Example of an expected result after executing `show-incomplete`
+image::ug_figures/showIncompleteCommand.png[width="600"]
-_{explain how the user can enable/disable data encryption}_
-// end::dataencryption[]
+In the example above, there are many overdue tasks. The task list can be further scrolled to view all the tasks.
+<<<
+
+If you do not have any tasks that are incomplete in your task list, the displayed list will be empty and a message will be shown telling you that you currently do not have any incomplete tasks!
+
+[.text-center]
+.Example of an expected result after executing `show-incomplete`, if the task list does not have any incomplete tasks
+image::ug_figures/showIncompleteCommandNoIncomplete.png[width="600"]
+
+The corresponding message is shown in the Results Display.
+// end::showincomplete[]
+
+<<<
+
+// tag::ug-pin-sort[]
+[[pin]]
+==== Pinning Important Tasks : `pin` [Coming in V2.0] (Yao Jie)
+
+You can pin important tasks to the top of the task list with the `pin` command. +
+Pinned tasks will always be displayed in the Pinned Tasks group in the task list. +
+Trying to `pin` a task that is already pinned will unpin it.
+
+==== Sorting Tasks : `sort` [Coming in V2.0] (Yao Jie)
+
+You can change how tasks are sorted with the `sort` command.
+Format: `sort SORTING_ORDER`
+
+Valid `SORTING_ORDER` values include `date`, `module`, and `priority`.
+// end::ug-pin-sort[]
+
+<<<
+
+// tag::calendar[]
+=== Calendar (Amanda)
+
+JelphaBot also comes with a built-in calendar view that allows you to view your overarching tasks due on a monthly basis.
+Dates that have tasks due would have a dot indicator shown on the calendar.
+You would also be able to navigate to specific dates to view your tasks due for that day of the month!
+
+==== Viewing your calender : `calendar`
+
+You can enter the `calendar` command or its shortcuts `:C` or `:c` to manually switch to the calendar tab.
+The calendar panel will then show you your schedule for the current month with today's date highlighted. +
+
+Format: `calendar` +
+Shorcut: `:C` or `:c`
+
+[.text-center]
+.Example of expected result after executing `calendar`
+image::ug_figures/CalendarTab.png[width="600"]
+
+[NOTE]
+Highlighting of Dates: Today's date would be highlighted in dark blue, while other dates would be in light blue.
+
+<<<
+==== Changing month and year view of your Calendar : `calendar`
+You can navigate the calendar panel to another #month# and year by specifying it. The calendar panel would be updated accordingly
+while highlighting the first day of the month.
+The task list panel on the left will display the tasks due on the first day of the month. +
+Format: `calendar MONTHYEAR`
+
+****
+* For MONTHYEAR format, it should be MMM-YYYY, but it also allows some other formats shown when your format is invalid.
+****
+
+Examples:
+
+* `calendar May-2020`
+
+[.text-center]
+.Example of expected result after executing `calendar May-2020`
+image::ug_figures/CalendarView.png[width="500"]
+
+
+This command should display the calendar for the month of May in the year 2020 in the calendar panel (on the right) and display the corresponding tasks due for 1-May-2020 in the task list (on the left).
+
+[IMPORTANT]
+Format of the month in MONTHYEAR (MMM) input has to have the first letter in upper-case. +
+E.g `Mar` instead of `mar` when specifying the month of March.
+
+[NOTE]
+Dot indicator showing tasks: Dates that have more than 3 tasks due would have a red dot indicator, while dates with at least 1 task but less than 4 tasks due would be represented with a green dot indicator.
+
+<<<
+==== Showing tasks due on a specific date : `calendar`
+
+Displays the tasks due on specified date, while highlighting that day on the calendar +
+Format: `calendar DATE`
+
+****
+* The date specified *must be for a day within the date range displayed in the current Calendar panel* for the corresponding date to be highlighted.
+* For DATE formats, we recommend the format to be MMM-dd-YYYY, but it also allows some other formats shown when you type in the command word.
+****
+
+Examples:
+
+* `calendar Apr-6-2020`
+* `calendar Apr/6/2020` +
+
+[.text-center]
+.Example of expected result after executing `calendar Apr-6-2020`
+image::ug_figures/CalendarDate.png[width="600"]
+
+This command should highlight the 11th of April in the calendar panel (on the right) and display the corresponding tasks due in the task list (on the left).
+
+<<<
+
+==== Navigating directly to today's date on Calendar : `calendar`
+
+You can directly navigate to the current day's date in the calendar view.
+Format: `calendar today`
+
+Examples:
+
+* `calendar today` +
+
+[.text-center]
+.Example of expected result after executing `calendar today` on 13th April, 2020
+image::ug_figures/CalendarToday.png[width="600"]
+
+This command will display the corresponding calendar for this month and highlight today's date in the calendar panel (on the right). The task list panel also will display the corresponding tasks due today (on the left).
+// end::calendar[]
+
+<<<
+// tag::productivitytracker[]
+=== Productivity Tracking (Jel)
+
+JelphaBot automatically tracks your productivity within the day, and displays a progress bar which allows you to track the completion progress of the tasks which are due in the coming week.
+You can see the progress bar fill up as you complete more tasks.
+
+JelphaBot also dynamically provides feedback in response to your achievements and task completion rate.
+Hopefully, this would make you even more productive by encouraging you to get more done!
+
+==== Tracking your productivity : `productivity`
+
+You can enter the `productivity` command or its shortcuts `:P` or `:p` to manually switch to the productivity tab.
+The productivity panel will then show you your productivity for the day. +
+
+Format: `productivity` +
+Shortcut: `:P` or `:p`
+
+[.text-center]
+.Example of expected result after executing `productivity`
+image::ug_figures/ProductivityTab.png[width="600"]
+
+[NOTE]
+The progress bar and the text following it only shows tasks that are due within the week JelphaBot is running.
+
+<<<
+==== Starting the timer for a task : `start`
+
+You can start a timer for your task. +
+Format: `start INDEX`
+
+[.text-center]
+.Example of expected result after executing `start 1`
+image::ug_figures/startCommand.png[width="600"]
+
+****
+* Each task can only have 1 running timer.
+* Starts the timer for the task at the specified `INDEX` if timer was not already running.
+* The index refers to the index number shown in the displayed task list.
+* The index *must be a positive integer* 1, 2, 3, ...
+* A completed task cannot be timed.
+* New timer entry under "Running Timer(s)" in the productivity tab will be added if execution is successful.
+****
+
+<<<
+==== Stopping the timer for a task : `stop`
+
+You can stop a running timer for your task. +
+Format: `stop INDEX`
+
+[.text-center]
+.Expected result after running `stop 1`
+image::ug_figures/stopCommand.png[width="600"]
+
+****
+* The task has to have a running timer.
+* Stops the timer for the task at the specified `INDEX` if timer was running.
+* The index refers to the index number shown in the displayed task list.
+* The index *must be a positive integer* 1, 2, 3, ...
+* Timer entry under "Running Timer(s)" in the productivity tab will be removed if execution is successful.
+* Time spent on timed task will be added to the respected time spent section in the productivity tab.
+****
+
+[IMPORTANT]
+Exiting the application before stopping any running timer wil cause all recorded time since the timer was started to be lost.
+// end::productivitytracker[]
+
+<<<
+//tag::reminder[]
+=== Set Reminders (Dian Hao)
+JelphaBot allows you to set reminders for tasks and manage your tasks comprehensively!
+You can view all your existing reminders from the reminders tab.
+
+==== Viewing your reminders : `remindertab`
+
+You can enter the `remindertab` command or its shortcuts `:R` or `:r` to manually switch to the reminder tab.
+The reminder panel will then show all the reminders that you have set.
+
+Format: `remindertab` +
+Shortcut: `:R` or `:r`
+
+[.text-center]
+.Example of expected result after executing `remindertab`
+image::ug_figures/remindertab.png[width="600"]
+
+Every `Reminder` will show the `Task` `s module code, description, due date, the days that will be reminded before the deadline, and the hours that will be reminded before the deadline.
+
+<<<
+
+==== Adding reminder : `reminder`
+
+You can add a reminder to your specified task to remind yourself of the task if the current time is within the time-frame specified by you. +
+
+Format: `reminder INDEX days/DAYS hours/HOURS`
+
+[.text-center]
+.Example of expected result after executing `reminder 1 days/1 hours/1`
+image::ug_figures/addReminder.png[width="600"]
+
+
+
+
+****
+* Adds a reminder to the task which is at the specified `INDEX`.
+* The index refers to the index number shown in the displayed task list.
+* The index *must be a positive integer* 1, 2, 3, ....
+* `DAYS` refers to the number of days before the due date of the task when you want to be reminded of it.
+* `HOURS` refers to the number of hours before the due date of the task when you want to be reminded of it.
+* You can only specify `DAYS` to be in the range 0 - 7 inclusive.
+* You can only specify `HOURS` to be in the range 0 - 24 inclusive.
+* Every `Task` can only have one `Reminder` .
+* A `Task` that is completed cannot have a `Reminder` .
+* A `Task` that is reminded but is not completed after the deadline will still be reminded for.
+* A `Task` will not be reminded if the task is completed but it has a `Reminder` .
+****
+
+<<<
+==== Removing reminder : `delrem`
+If you would like for a task's reminder to be deleted, you can use the `delrem` command to remove the reminder of that task. +
+
+Format: `delrem INDEX`
+
+[.text-center]
+.Example of expected result after executing `delrem 1`
+image::ug_figures/delReminder.png[width="600"]
+
+****
+* Removes a reminder associated to the task at the specified `INDEX`.
+* The index refers to the index number shown in the displayed task list.
+* The index *must be a positive integer* 1, 2, 3, ....
+* Whenever a task is deleted, the corresponding reminder will also be removed.
+****
+
+<<<
+==== Reminding you with a popup notification
+
+Whenever you start up JelphaBot after adding your reminders, JelphaBot's reminder window will popup.
+The popup will show a list of tasks that will be overdue soon, and tasks that are past their deadline but have not been completed.
+
+[.text-center]
+.Example of expected result after tasks are being reminded.
+image::ug_figures/reminderpopup.png[width="600"]
+
+****
+* Reminders will persist until you either complete the `Task`, or delete the `Reminder`.
+****
+//end::reminder[]
+
+<<<
+
+=== Colour-coded module codes [Coming in V2.0]
+
+Users can customise the font colours of different modules to better distinguish between different tasks.
+The module codes displayed in the Main Window will be similar to the tags displayed to make it easier for users to view them.
+
+<<<
+// tag::faq[]
== FAQ
-*Q*: How do I transfer my data to another Computer? +
-*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder.
+*Q1*: Is JelphaBot free? +
+*A*: Yes, JelphaBot is completely free to use!
+
+*Q2*: How do I transfer my data to another Computer? +
+*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous JelphaBot folder. +
+
+*Q3*: How do I save my data? +
+*A*: JelphaBot automatically saves your data whenever you make a change.
+There is no need to save manually.
+
+*Q4*: Can I add multiple tasks using a command line? +
+*A*: Sorry, we currently do not support this feature.
+We will consider this in v2.0.
+
+*Q5*: How do I add tasks with no deadline or description? +
+*A*: Sorry, we currently do not support task entries with no deadline or descriptions.
+We will consider this in v2.0.
+
+*Q6*: Do I need an Internet connection to use JelphaBot? +
+*A*: No, you don’t.
+JelphaBot works completely offline.
+// end::faq[]
+<<<
+// tag::commandSummary[]
== Command Summary
-* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +
-e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
-* *Clear* : `clear`
-* *Delete* : `delete INDEX` +
+* *Help*: `help`
+* *Summary*: `summary` or `:s` or `:S`
+* *Add* `[d/DESCRIPTION] [dt/DATETIME] [m/MODULE_CODE] [p/PRIORITY] [t/TAG]…` +
+e.g. `add d/Project TP dt/Jan-01-2020 23 59 m/CS2103T p/1 t/pair work`
+* *List*: `list` or `:t` or `:T`
+* *List by Date*: `list date`
+* *List by Modules*: `list module`
+* *Find*: `find KEYWORD [MORE_KEYWORDS]` +
+e.g. `find Tutorial Assignment`
+* *Edit*: `edit INDEX [d/DESCRIPTION] [dt/DATETIME] [m/MODULE_CODE] [p/PRIORITY] [t/TAG]...` +
+e.g. `edit 1 m/CS2105 d/Tutorial 2`
+* *Done*: `done INDEX` +
+e.g. `done 1`
+* *Delete*: `delete INDEX` +
e.g. `delete 3`
-* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +
-e.g. `edit 2 n/James Lee e/jameslee@example.com`
-* *Find* : `find KEYWORD [MORE_KEYWORDS]` +
-e.g. `find James Jake`
-* *List* : `list`
-* *Help* : `help`
+* *Clear*: `clear`
+* *Exit*: `exit`
+* *Show Completed Tasks*: `show-completed`
+* *Show Incomplete Tasks*: `show-incomplete`
+* *Add Reminder*: `reminder INDEX days/DAYS hours/HOURS` +
+e.g. `reminder 2 days/1 hours/1`
+* *Delete Reminder*: `delrem INDEX` +
+e.g. `delrem 2`
+* *View Reminders*: `remindertab` or `:r` or `:R` +
+* *Productivity*: `productivity` or `:p` or `:P`
+* *Timer*: `start INDEX` or `stop INDEX` +
+e.g. `start 1` or `stop 1`
+* *Calendar*: `calendar` or `:c` or `:C`
+* *Calendar Date*: `calendar DATE` +
+e.g. `calendar Jan-1-2020`
+* *Change Calendar View*: `calendar MONTHYEAR` +
+e.g. `calendar Apr-2020`
+* *Today's Calendar View*: `calendar today`
+// end::commandSummary[]
diff --git a/docs/UsingPlantUml.adoc b/docs/UsingPlantUml.adoc
index cfe2533ea84..120d5619638 100644
--- a/docs/UsingPlantUml.adoc
+++ b/docs/UsingPlantUml.adoc
@@ -39,7 +39,6 @@ After installing the `PlantUML integration` plugin, simply create or open any `.
image::EditingDeleteSequenceDiagram.png[]
Any changes you make in editor pane on the left will be reflected in the preview pane on the right.
However, do take note that these changes _will not_ be reflected in the developers guide until you export the diagram.
-//TODO: Discussion about why we're not using asciidoctor-diagram
== Export PlantUML diagrams
@@ -88,7 +87,7 @@ For example, `skinparam backgroundColor transparent` turns the background of the
For a comprehensive list of ``skinparam``s head over to the https://plantuml-documentation.readthedocs.io/en/latest/[unofficial PlantUML skinparam documentation].
-***
+'''
=== Repositioning elements in PlantUML diagrams
diff --git a/docs/diagrams/AddReminderSequenceDiagram.drawio b/docs/diagrams/AddReminderSequenceDiagram.drawio
new file mode 100644
index 00000000000..7762c073287
--- /dev/null
+++ b/docs/diagrams/AddReminderSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/ArchitectureDiagram.drawio b/docs/diagrams/ArchitectureDiagram.drawio
new file mode 100644
index 00000000000..4ddb157bbe6
--- /dev/null
+++ b/docs/diagrams/ArchitectureDiagram.drawio
@@ -0,0 +1 @@
+7Ztbd+I2EIB/DY9wbMnXR0LCpu1um3Nyut08CluAToTl2iKB/vpKWAZfhEMcbJLs8pBYIyHJM5/Ho5EYwMlq8yVB8fIbCzEdACPcDOD1AADXc8RfKdhmAhsqwSIhYSYyD4J78h9WQkNJ1yTEaakhZ4xyEpeFAYsiHPCSDCUJey43mzNaHjVGC1wT3AeI1qX/kJAvM6kH3IP8FpPFMh/ZdPysZoXyxupO0iUK2XNBBG8GcJIwxrOr1WaCqdRdrpfse9MjtfuJJTjip3zhj4fJbfDnvfP9r+369x8z7I4f3aHq5QnRtbphNVm+zTWQsHUUYtmJOYBXz0vC8X2MAln7LEwuZEu+oqo65Ql73GvKFpI5i/gUrQiVANxi+oQ5CZCoqM8/nwxOON4UROp+vmC2wjzZiiZ5raV0q+DKi88HSzmuki0LVrKhEiJFx2Lf9UGB4kLp8BX6tF7Wp+Aglpco4Cx5bxq1ywqFRl2jlk6hXenTflmfOArH8kEXpYCiNCVBkwJhKwXisOQl6uor6Mdu0E+CKeLkqexbdEpTI9wxImZy4N2omKfKccrWSYDVt4q+oNqRX+kI+CO73BVHyQLzWlc7K+5vvL1hc/9+XsviDeE/xLUxslXpQZbU9fWmWNiqwpxQOmFUPotiUEG8hwxj33upxnZ3NR+WH2D5I7/40T/sr6VJTC+nZ5tLeqYJdEJTJGZVwEkWH1TrXeEA1K60LeD1RgrnBoIG0lEIBYOTyeel0PTtkVH8OC2hbB5FINs0Ste86uIEh3Jl1hK4zr9rllcM012APBYNTDveHCrF1UL+V/F31pWYWtZbVld7It4a2ZWRRcAwgK1D1plKDatbKEK++3Qc0UCnxlctpDFNs0676djHyX5TUGN2EtXkXscUYHtFvzOyGj2PLNzhhIh7w8nP906EpjHynYInsCqRkdfO/0C3GmJ5fYdYzgfD7DO/9CRmuhdOHjC1jeSFextVkBV99Uwa6DaYL1FmN1OWh2z7GK3wrYaQrUoicjy9w5u40P7YDs/0GgMj0HZJWVmb1jo6wqCAAm0LzWLZIG2Y/pFxDkhnPZ4X8G7WF925Umyblh7gK1AIxj4kwMBvdKVWe1daeWM7/S4KAOzUi7ZfjH5qmCy/kruw2nrAWvLU7fktfELy+ZeT6s1J6dMYOWSOVY3RTnZTtlWN+KzqUrVr0nQL2FemL1xd+mLCVisWpZdJYJgzZGKgX+U6N+PpO0lg7N9vBZChoUlgeF3lL2An4X6I0uXelu1M8yE9hV3d1Km+Nk51DJZfDuw92BwXdewk4Al7y78oOZkS0Lh105aZarfeZZHpZJn10yJjd4OM/a6Qed2iKWIRfjHibbntV41uYXAkh3Rl+G1zSJk2m/ThvSsGHReU8fBaLq7c2uK8m/SS4xnaCR+dF2xs3006Cp4h/tZuH/7922VCb8Pw/RM2mPoOvWvHZDTHofZ5zuLTU4XzfKG3bk/nHJb/yhbiTXoR4zviM52+uO1zaeNrN477Nb7bkfHvOUvkOdiLmP/EvZZLm9+/+KPvdWT9ci97dyDaT4T6cHIUi0w8S6qSfvk5Mc7qmx+nsv8PLu4+rBMW5PnhZLLanYsvGkLeutAOHVOyiISMs7gg/YpmmN6xlHDCZO2Mcc5WogGVFVcoeFzszK4zw26wcRpn5/elwVBemJONBOVKzed6ybk8+D+WmgDTIIyMEQlYNCcCqGQUiBHBNEQciX9SLgK9qZjhdjhDYqE4RFGYMBIO6ZAySknM4qFsNRTwPYqWMoE+DVmwXgmzD03gjeJoIQYv89rvgWzoj0B5f8LbnyMpHnM3c2EJJbOaZD4bTEAH0zlSwN8QiS7jSEIbe6GlcyQemMnNwG4tDYzqPlTdzL7GX/iv9xeiePjdSbYoOfx4B978Dw==
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.drawio b/docs/diagrams/ArchitectureSequenceDiagram.drawio
new file mode 100644
index 00000000000..3c826ac415d
--- /dev/null
+++ b/docs/diagrams/ArchitectureSequenceDiagram.drawio
@@ -0,0 +1 @@
+3VpZc6M4EP41rso+JMVhsP3oI3NVtmp2POejAjKmLCMvyIm9v35bIC6JYHDATiUPDmqJRnR/fYqBOd8ePoZot/6bupgMDM09DMzFwDAmhgW/nHBMCENrlBC80HcTkp4Tlv5/WBA1Qd37Lo5KCxmlhPm7MtGhQYAdVqKhMKTP5WUrSspP3SEPK4Slg4hK/eW7bJ1Qx8Yop3/CvrdOn6zbk2Rmi9LF4k2iNXLpc4Fk3g/MeUgpS662hzkmXHapXJL7Prwwm20sxAFrcsO3L4fb2f74YftP5P3EP3Uzmk5vxwmXJ0T24oXFZtkxlQDse8cv91vy4K8w8QMYzeC5zHf8HYofDnNTh9GQT+DQ32KG4XpBxPqvOW32vPYZXu6Qw3k+A2aAtmZbAiMdLkGPDMEtYTYmBO0i/zHejgaUEDv7MPKf8DccJXDh1CfM94PIlPheADRGOeMInuMH3nc+WJg2UAh6xGSGnI0X0n3gzinhu4b3NFfxHyyhe8Y3Pc8Qxfmr0hYK4A/GhwJJSP8jpvDK4RGWpLOaQIIwhbEYPue4SrGyLkDKTIlIQNnLOOfahguh8BbK180K7dv/7jkiZ2DHoDGY1XOago2C4mQFPFLG6BYmcOBOuSFyGqHOJibB9n9zyd6BwaSEP0C41e40zUgpi4OQfjI6FkcFTL2goDrAMxR6uG6dLgwBuyX/oCq3oL1UoSEmiAFAy86oQnuC21fqw54LOKmEScogovvQweKeor1LbCb1bBIJKGxiIGWvdz62hlXQIhxEKxrv0sksL0dXaoMFku3F/83pj88pA9hPwkPMNXRY1/FLlc5k5RNS8DyaNplonB6xkG5waca2ta7cz7gMiMwdFRA8qvI/Wm/+xzgdfQoq2HGsxnuwZgNrIemUhmxNPRogUtSqIlEuaa1OBw39yLCt+M2y9G1V+HqF8LPbuhe+pQgfHwDCDN/UB4G/uooCbdBep4OTvty6misflpU+OdOV60Y9n559OYToNnbaBAN0hwOOLxStsSvug2mR/4+r0MGxMZ+3RsdJrb82WtvDO6ukHSMtAdqqWUKLwqdnNasO4ZUh+4F6vvN+oraCSDP2WGosqUFq66ht6m8ualeldleK2m19gtVa/NWO90TU1uVkuzPhp4GgIPwkRn9H0eaG9RebM0lntRuUarqdlWp/BsVKrfu6zWoY6/XJ1YK9hBVdPzfayyYvM+o5DqT2fN1wn5l8O4AkQq5ZZ18oLZBSNl1O5M9MChQ+fYNB7RFF6Al/wWS3RjPKbpDrhjiaUbq5pPPhbSJLaRwN34IDGl/NAclQsTsqNxRGPWOuotwwp6/JRcWpxHtJRKUkKPOUlXbTVftoKKOrIhEdXzYRnVw+Ec0k+pIOGnoTu634zXKNmeUEp/pHfQl/VCH7VxWLS0ZDfhb3Xq10MZwNLatlptPaSi2pyTsZKzC5cLXY4ITxUkaaqaChkY7aSl+uABo2eeV2XnfV4hsq1fsXvtSFq4hPVcLvrcFuqP20JWTOPIek8APiwYoyeNK4FMNc3vc5teitkEilCV5xFynOuh/i0cKoTq3jQ++4BMvy4d+DtB4rlPGKWs9U38lyTG96IGtcqJ8rpzmjZkk0CBodC8uELb34GFuK52Pp44365Sm4c3wmz+80DVfTqx8R2LyMWTBPVgZmGTwBjUOz5A6yry1SFDuAp9ijyJXi1nfdGPpVwbuM5w4C6EQv68VQvcjwknmWXpVoXbwZc/ocum+zNLRRSTHm+MxDFrm7pjDqu6HyJg7Tatz5hRRqS47WtM7sVmQ3Zoz0jhQKw/zzvGR5/o2jef8/
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml
index 7790472da52..a13603a57e8 100644
--- a/docs/diagrams/BetterModelClassDiagram.puml
+++ b/docs/diagrams/BetterModelClassDiagram.puml
@@ -4,18 +4,21 @@ skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
-AddressBook *-right-> "1" UniquePersonList
+AddressBook *-right-> "1" UniqueTaskList
AddressBook *-right-> "1" UniqueTagList
-UniqueTagList -[hidden]down- UniquePersonList
-UniqueTagList -[hidden]down- UniquePersonList
+UniqueTagList -[hidden]down- UniqueTaskList
+UniqueTagList -[hidden]down- UniqueTaskList
UniqueTagList *-right-> "*" Tag
-UniquePersonList o-right-> Person
+UniqueTaskList o-right-> Task
-Person o-up-> "*" Tag
+Task o-up-> "*" Tag
+
+Task *--> Description
+Task *--> ModuleCode
+Task *--> DateTime
+Task *--> Priority
+Task *--> Status
+Task *--> TimeSpent
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
@enduml
diff --git a/docs/diagrams/CalendarCommandActivityDiagram.drawio b/docs/diagrams/CalendarCommandActivityDiagram.drawio
new file mode 100644
index 00000000000..134cddb1673
--- /dev/null
+++ b/docs/diagrams/CalendarCommandActivityDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/CalendarUiClassDiagram.drawio b/docs/diagrams/CalendarUiClassDiagram.drawio
new file mode 100644
index 00000000000..8644b3e06c5
--- /dev/null
+++ b/docs/diagrams/CalendarUiClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/CalendarViewSequenceDiagram.drawio b/docs/diagrams/CalendarViewSequenceDiagram.drawio
new file mode 100644
index 00000000000..88efb434c7f
--- /dev/null
+++ b/docs/diagrams/CalendarViewSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/CommitActivityDiagram.drawio b/docs/diagrams/CommitActivityDiagram.drawio
new file mode 100644
index 00000000000..d11d0143da1
--- /dev/null
+++ b/docs/diagrams/CommitActivityDiagram.drawio
@@ -0,0 +1 @@
+7Vrbbts4EP0aPzbQ3dZj7CRbFC0QJNh22zdWoi22lKil6NjO1+9QpC6U5MTZyDbQJAESczQcUmfmzIwoT9xFuv2Lozz5wmJMJ44Vbyfu1cRxQseHv1KwUwLPcZVgxUmsRHYjuCePWAstLV2TGBeGomCMCpKbwohlGY6EIUOcs42ptmTUXDVHK9wT3EeI9qXfSCwSJZ0500b+EZNVUq1sB6G6kqJKWd9JkaCYbVoi93riLjhjQn1KtwtMJXYVLmrezZ6r9cY4zsQhE74+3kbfwh/k7tLJsZ8vBZ3yD9rKA6JrfcN6s2JXIYBjAEQPGRcJW7EM0etGOudsncVYLmPBqNH5zFgOQhuEv7AQO+1dtBYMRIlIqb5aCMTFpfQWCDKW4Up2QyjVZnEWVxoRRUVBIiXUKsoMZ7/xglHGy627l45lQQC6c3VT8k72gqdFBVvzCD+BmAYIdrfC4gm9sHYxUAOzFAu+g3kcUyTIg7kPpIN0Ves1foQP2pUvcKtzgFspBQ5JpDcJEfg+R+Vtb4DFpnNQkStiLclWOnm+BMRbINue/JXwVwFu14g/YC7w9mnM+xjpCb6nmaNTh6+Hm4aHFbeSFgUr2eig+m+DK0uWiRuUEiph/4p5jDIkp2+J+Efav/D16Ls2JT9fbaul5WCnByPSbnog7ew9MXUw7/TUW0Zgi00s2uFFaERjHY6VEXULel4n1OqN/P/oC84RbJXT7ZbLmwAYdvrZAjQDgOvNykFrt3LYbLcc7dqjW8wJeAjzM0bu7EiRa5tZNOzErdpYL27BP2jXUsulQrF/ncAz17HDTjvyjL7nWx3aqB2MSqLp8ymcJyz9uS6er4tGuXsiWs1quVwunSg6ToG0Z2eukGEP3r8LoBQQaYujtYA+XjbqaYqyuIf7ENpN/iobER7pROVLiiJKVplMIICW5O1cYkmgc7/UF1ISxxTXzqna99IUZLpC2Sq9B8uSbAUj2ccIjvENPCcoia0lX9hDI8jwppVnryZTcGfw71q28vMmLdeiiXvZup4JInZ3JatZdj2g7SyaQSubDpsrM+zw3DrLvnhmgVepDML2RPlE1lKJ1vwBXGNoTKZXXWLsC//9hEkYJ4+Q4lFFtD35fgQCeV0C2QMEGmKQeywGVRs4T5l/SW93rjI/YmU+Vq/om1HldjvFkSpub53uAcDL9I9Tce3+CcMdmCQY4JVNUfH7oErQCtb3ovAGi8IRa0BosmLomME+bQ0YOr0JqFAxmRlkqYCW+HxQwQvOtGwr37a9GKzK//687r7KPozI9GJ9wjRP0BxU/atqIdi4WkvP7HIU8BYmLQ9nHsewUfSzNCU5q/Mc2PXncgs9Jh7P+b7nm863/b7zp6dsoauD5RM3ANWzc+tx+fuk/bQ8/OzcI2wYWvAzcpnWbwyO/wT9Otq6Pdreo7LKNQSTLy/gz69KcC+QwJ9JId6L4HsRfLYIjlHtguDCMXOeO1TwgumF38963tFK3tDZuqpEMvm/quRhWmCzsimTf3hlm3Uebad9L3unLGwqOf+xZ2/1UcK5zt6cfvnpdxL1Oz8Ty1xeh5xYlqM+bpali3oP6frKGIi6gYGob/URdU/Zhztv5IXfoa3a0Q9KbK9jYs8rtecNzTqG9py4jHXI4fQPvt8jZeRIuTC7Fi847PXrAabqRPPqaIFh830epd58Kcq9/g8=
diff --git a/docs/diagrams/DeleteReminderSequenceDiagram.drawio b/docs/diagrams/DeleteReminderSequenceDiagram.drawio
new file mode 100644
index 00000000000..52337e11035
--- /dev/null
+++ b/docs/diagrams/DeleteReminderSequenceDiagram.drawio
@@ -0,0 +1 @@
+7V1bc6M4Fv41rpp9sAtJiMtjku7s1lZPbe907W7PvGzRoNjMYOMBnDj761cYxEWSbUEswHH8kBgZBNZ3Lt85R5Jn6GG9/2vibVc/xwGJZtAI9jP0aQYhMGxI/+Utr0ULMkDRsEzCoDypbvgW/o+wK8vWXRiQtHViFsdRFm7bjX682RA/a7V5SRK/tE97iqP2XbfesryjUTd8872IPccC1+3/CYNsVbQ70Krb/0bC5YrdG1hu8ckPz/9jmcS7TXnHGURPh1fx8dpjfZV3TldeEL80mtDnGXpI4jgr3q33DyTKR5cNXHHd45FPqy+YkE2mckH6z9+MZ+e79f2/7uPn323jt/0/4rmLim6evWhXDskM3X2Jl6H/s7eh3z0pHz57ZUN2+Mok79SYofuXVZiRb1vPzz99oUJC21bZOqJHgL59ijfZo7cOo1w+/k2SgHaaN4dR9BBHcXLoEnmeYdBxQ/dplsR/kMYntm0YDw9lR432cqTRffn4JMnI/ujAgGq4qSCTeE2y5JWeUl4wt0uEShmGTnn8UssDYCiuGrJglW1eKYTLqusaBvqmRKILKqYMlb+TaLvy7uPsq5ektwBMBcR0gMEyYD6RiGTkF7IO6fgnD/F67W2CWwHJNNsgIVcECeJBQbIEkAJ6SIGif6VYvX+ULM7GYShRJVeCkqkLJWAYMl0qKcYAeEDDgFiGh/Vo0JdePFzYxsOyRDxkcGhTGsCI2xGf8/4hoWSWw0TmboxhQZHSs39twj93lQ37Eqa3gE41yqfQMYdFxxbR4YEgm+Auj1Po0SbeEKWBLzohAQtd1AerMRYyl8vaEhJ5Wfjc7l42PuUdvsYhvXFNmKuOXplWYG6Q03iX+KS8rhmUnOuq4nisp8xLliQTejogVn3zt4Do9gEx8NLVQb2AEqIUt+T1e66NC+TarOHX/KKFYULW8GlfKmxx9No8+kqSkH5ZkpSNkxcSwPFCu6+IADpo2K1f7W5NuMBwYJFxOomMH3lpGvrvU/XfAuvpjnSjCETCQ/bE32Xkpxm0/tzleZl7SkYTsqZnwbrtLwLY1K1lbXjbPrI0Gk2HWjZ5Ubjc5DJC4c1V+z53kqHvRXflB+swCPLbSH1428ufFKm3ZUggR40QFp1vZbmbYge1OV8AtSlhw1ofCE9lrI0zhlpVe6FRCPfJ7+eMque4jbfbU8sROpIdGEzLRQa9zTMzZeT/oeq8qvOA2aKmI5ngadT0XjS7P0NrqTwYTuWLrO9YGo+O5fE6qzwXqJnG0CqvQM8uER9fQNsQOmJnWykHibLx8dYFta1bPNTJr+7DrFAx13HK44NbXeQ6XhzXapYfvDYO+gZA9MkPkjtdZ2tyNtfsy6n5XLzJG2XdqsfudwWqh3kzJaG0MtVD2jQPSjKwOv0c1OLoxlIibLVNKeZlX1WJsGUu2l2ZQ+ekGPA3mGBAXH7hDTCe6Ug7iJLcPbSirMSGfvLklV6JhRsMpqqBvlvm/w8hSyNWaYcoRaf0KYt+i0sEgZlG5HIBy82TJmyIllsqovpCFCiZsHElfk9aCZYMHh8OXHDwJJMqLs84gdlinIYJOjPO2ne2kkJ1wDhAjGiN6mNtOnCNF2hLkmkskNnPWlsWXjgW393ABlshzzARJbZ5JZZMHxiYvOqriVRK3FDgM8rLFBW0FdU+p6ktMq2utucDTCZb5/O+cNQsUOVLmWD1DUXxOR6nXZsHyGMoC2QvuRovkuJmWoCeMoBMfLoj3TLAzF17JuAkebE+X8EnhbBk4oxs3ow+X4HERMftwWLxsEhc+MCwdMs69Ms/XdKpmqOaSZtLODk8X1U1k3xHeOgaKZJlKsYCfir5Q6s388nzh87Ijk8hH/FBfuQTFjgxoEEtGzxlSaivHRh26cqHG3OswDxCX0dzrECkoQIqE0kszNm0qmr6BxAGT5ZYsFi4pYGW3Mj0j5GL0Pz8j/5zuhFyqQNspAlN3qIObBUVUlPpytvmb8P1YcFwU2J4I5fF20brF+8Hib7GaZiFcf7pjzjL4jU9Ico/uK/WCMuWRRxudpdui4XNuTh57OAp3OfSe18+z6dVluUrou/y0YGPfrCBi9CPN0+HFSALn94RPgZe5tF/eXtK/5M0pTIYetH8hfyYgzmViMcc0kc/ilMy95M4TeeEak0yf0nizXKekN/pzfNU3mK7WV7AmGATLdhVDHxJlZ2exfhSa+VZ3Xx5o2IqmOQp1xwGNEsjRVmlwNjQWFCDws/+70zKufV29tDpSFNhcsdEOABfXLAVK4QaV1qZ00pNTFZpjmQU+vvy0XMTZrfcxE0b6lFrwza3RMSmgbNjCrXirgLoYr5bMLAAiqmUoLWHwE/J7a0SsB0FF2HJfIQ+F9FtFknPMLEyGbhpMNSK0dpCS4VMuaVqRIr671hGxOWMiMtTCmWzwVujwfmemIoTxHEifM/l+Z6pxvcAv7DjcsqMPyoS+VZjfNDSVxsAAC5fk7CHTsPg65kjSccLy0f+XBpUn0Z0i4DG48FT1yrBM1gXSTCcV1bt+iUSoA+i6mJOkWW+bViiihWYwWj1jD4EV1XjVYgqc1IKRBWN6pv5he1v8M1Q9M18uka77bieJbMAQU6lbazkm/XVd7E41TQh6/j5pi0v4OvwNpbgNKzpZXebPImaxA4keNR6NACinl+EqCGeqDH7MZSxtbqt853g5Cx1Tz6efwY2t4rXYdv19fDQUOhraJnRF/5J3Y6/S56vZs4egNxeYkJuQxlqYZdJxXoXHXjvtXHaNj8hPfXIR5Jux58MyJ+slrTiGS4sd/pW0VyXiPHzQm2HswDq/ofvyVWzJZ1FDPGxb+nojj8Zlls5vSJmi6SsYM83yZoFdiLb5nZY1sx+40ODDbiqqeFCis/puzcFn4MUOtJNJ+wh6iu6C5+Tyf30n15D1V1I/gzOLe1ui0U+hOGkUXiDMEiqdMNbhkGmUbxTYXAvNu/OzReR2cc2vRaWGmqXim41i94UoN64YQENbvMG0zpbvHjLPunTn9XJ17J6LzitPMxo4tRtSU+fDBjLev06axaz3lbAGgt4fmql03dpqsNtyCB0pB14SToB3ZV7Mf9C0l2UCYLw7n6L6SgKzRBv2NklLMi8gvqf47ZHz0WS0Rs0Pnb05fOn4hxHc3ncdkRuXz5lW84CGzWdarNs13QXrnu0tKTbKjrdEiwfnPuUiPTn3I7rnuDcguhplwp9K1+uKu3GL0dz+d14VbdjEC7UjqC+qOmd78LBb0MADH6uee8fGBO70i4GQ2xgMHlE7QtZaaGji8FJD+tf4y5Or3/0HH3+Pw==
diff --git a/docs/diagrams/DeleteSequenceDiagram.drawio b/docs/diagrams/DeleteSequenceDiagram.drawio
new file mode 100644
index 00000000000..3bf016d761d
--- /dev/null
+++ b/docs/diagrams/DeleteSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/ListCommandActivityDiagram.drawio b/docs/diagrams/ListCommandActivityDiagram.drawio
new file mode 100644
index 00000000000..719066e8190
--- /dev/null
+++ b/docs/diagrams/ListCommandActivityDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/LogicClassDiagram.drawio b/docs/diagrams/LogicClassDiagram.drawio
new file mode 100644
index 00000000000..996b8d035c6
--- /dev/null
+++ b/docs/diagrams/LogicClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/ModelClassDiagram.drawio b/docs/diagrams/ModelClassDiagram.drawio
new file mode 100644
index 00000000000..c7d0c3a9ce7
--- /dev/null
+++ b/docs/diagrams/ModelClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/ModelMoreOOP.drawio b/docs/diagrams/ModelMoreOOP.drawio
new file mode 100644
index 00000000000..1acf0b75b1e
--- /dev/null
+++ b/docs/diagrams/ModelMoreOOP.drawio
@@ -0,0 +1 @@
+7Vtdc6M2FP01fulMMiDxYT/GdjadTruzHWe3Td+0RgZNALFC3tj99RVGMmBwkB2w2Wz9YutKukiHc9DVRR7BWbR5YCgJ/qAeDkfA8DYjOB8BYBqGI74yyza3OFAafEY82agwLMi/WPWU1jXxcFppyCkNOUmqxiWNY7zkFRtijL5Um61oWL1qgnxcMyyWKKxb/yIeD6TVdCZFxa+Y+IG89BjI+X1Fy2ef0XUsrzcCcLX75NURUr7kRNMAefSlZIL3IzhjlPL8V7SZ4TDDVsGW9/twpHY/boZjrtMh+rj8SJx/HuiXz2sO/sSB+RTcWNLNdxSusZqHEwqH0xUVfjPcQ8p2Nc63dTbWaWmihcnxs+/fcJgEaCps0okYTu4nr5dI8K1CP+BRKH6Z2fVIGM72F4OzmSE++z7leaoxY8bxpmSS837ANMKcbUUTWQsdeQ8kRyey+FK64apJULrXUNqQ5Ji/91zgLH5IqE+BHXQK++eYfFvjR+T/TtKBQW+bVgX6vRzK2IOLYg87xV6gPjDErSri0Kgj3kR2qzfA7V7Inj4Pj+3QMm6BPTTCOx0TPn0eGOpuDfXrk97tFHQRd61DPBPR17CgB6Z761ahtwCsQT9ugB64fUE/7hT6OeL4kUQDAx7qAe9eEnjb6BT4BUd8nQ4LdtPSgt2+KOzdxvBznC4ZSTih8bCwt109ytuXxL7bQP4TI5QRvh0W8JahBXzT+tof8B1H8eIBv0hwPLB40hoP8Clv1ZA3a/Dg2LvLkjOiRAWsAo0SYKJS5oFMMfdpyhHjqrVHUERj7zEgsapSbS1l+EDCvSvPxwt5Wcp4QH0ao/C+sE5RSHzhah7iVXYjM+zJEoV30vyVck6j3aAEOH8Li3Frq+JTVlSF+aZS2qrShvC8G7Bl8UkNTvwuemUF1ekoNVK6Zkv8WnCjcmSI+Zhr7LoyhLRWtgrLVHaO4RBx8r16n5soJf1+omQnPuXUriZeTPMg3s7nK3uVk1cHjqDZ4ijH4xVHqiFdrVJcabNTwR6QNwijvs99F8LYE9zVJ/i5atrlU7F3QZmAAcjEPshPmsaZMnFBi6MhyKQpHXEFlRg9qaR/kbxBFrauLJzTZHFT1QXsRBZgcjyvc6oyLLvd1xFxdEb81pRQoQAVn2YVN+mOwXeigTlONvXg9RfdoPVHXnwuElwNYjGAR/L3p1LedlscDWAxcJpSRu9mMTBLnC0Y3LYYVJaCYmXofjFwdBcDeJosskgRjg+414k2rPr7FQjOlIdjtPsagkLq2+2f9Ll+9T2Frl7UpveqwZPVQG/33JXEaffVc/DkNAVPrTIQljJ9q0qoaKRXarUzRjfwaDqx8laimPWbOz43yq6/ibUmekQRdw5tS82SrEH6yrDh+NiwC+rlTrslYtPbxe6IOLzn4lU42fDwsg68aKcObVDPoVv9cLJh2GOzZXSwpUtPNJ78ZDTucHnXDYf7EIbGSqwdAIOzV/VOhGG8OjobNAjjAs9396wd6f/CKB1EuIow6vk9++ydYT0iqvm6njAc076OMJqOmbxnYfzogQ+wGw4PDCfwgSd3AXZDyH+BWEnlUa+XuOd4w6t6STmjz1gdO4lpnGVfyidRpEklZJaC3Zg1pGQi4nm71M1LQDheJGi3FrwwlOgr5YQzXLD6grLpnK7c6ZcPsxy+7dc4zCKKxX9rciYUf2CC9/8B
diff --git a/docs/diagrams/ProductivityClassDiagram.drawio b/docs/diagrams/ProductivityClassDiagram.drawio
new file mode 100644
index 00000000000..7e4aeb88568
--- /dev/null
+++ b/docs/diagrams/ProductivityClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/Reminderclass.drawio b/docs/diagrams/Reminderclass.drawio
new file mode 100644
index 00000000000..ae78e133c86
--- /dev/null
+++ b/docs/diagrams/Reminderclass.drawio
@@ -0,0 +1 @@
+7Vzfc6M2EP5r/NKZeBDi52PsJHfX6U07ybSXe9SBYqvB4ACO7f71FUYyIESABGNi2w8JWsFi9vu02l0Jj+B0sfkSouX8e+Bib6Qq7mYEb0aqaloG/ZsItqlAh0wwC4mbikAmeCD/YSZUmHRFXBwVToyDwIvJsih0At/HTlyQoTAM1sXTngKveNclmuGS4MFBXln6g7jxPJVaqpnJv2Iym/M7A8NOexaIn8yeJJojN1jnRPB2BKdhEMTp0WIzxV5iO26X9Lq7it79FwuxHze5wL5/9IPV9nm1/fHtGf77a/ky8a50LVXzirwVe2L2beMtN0EYrHwXJ1rACE7WcxLjhyVykt41xZzK5vHCY91RHAbPeBp4Qbi7Gt5Z09vplPY8Ec+TygM/vkML4iUM+QeHLvIRFZcfjz3xKw5jvMmJ2ON+wcECx+GWnsJ6LWb5LacUa68zIIECmXCeQxFCa2zqjESMQLO9+szG9ICZuYXJgcTihhczSyQcTW1LpS+rhBwTbpS9gB7Nkv+/Y285RxMqYxroF0qVpP1vQKnUQykAdq0qiqrLIJ7QHkVhD5CTP+0+3WAJ1SKYqikBE0iw1JUD4ah2hyP9jxaJ9b1yi/gxDnequLh4CW/tTv4VcpX3GLl/+t62RJHslNMnjWoLHkCTkMbqkzSwO9KwqfbUMdwP6jcwtPUeIZTNmB+B8DvtmuHwDJBU1LE+MCeudwfm3z55WeF7vCAUn/APEp3BrKw3mZV7dbBGd4ByKE8fRtMcWnBldgfjNwrK5vQxtAUMgX1sDK3uh+IN2p4fkscfjXb3SH4NVmfgWEUooX5sKIGs/CDYG/vudVI6oy3HQ1FEnKKJqT3C7SODY9f4mTTGOm/ebPKdN1vWKkEwnTIIKk0dUZowalVk4SyjilE4w3F9YIDdQr2vjFwOGf0NYELsoZi8FquEMrTYHf4KyG6k8BlXDJxsodyUPji7Kl/VExQZeoWz4IpSw5QU7cizf+wP8ElWBmnLpw2JH3PHP3PHGZWSxiGZBIyGTLIGxSRbEZmkjQ3dzj7m+4hlG+bbDD00sWSlkpbEqqbJe11YJb2GwgbRr6jKO+EXgxBVGUOtXwY0WJu4MKCOAdDqiAFUEWWAkn1gv2yQlWqq2eAHPm5KhfOBtM47HBpDWXVGwLAmvEfRMl3mfSKbJCWojPfDIKY2D3wqvtKkCUA9/i2WGi2taFnL5LXOfKgvqVODQ60zqg0m0I8Ym42wfu1scq8zIDvX1qoyg/NsOOm4inabHa7pCUBfbvKpsuLsrZcJoePs7FhKqX9rmkdTG8dv+USGqARk5JFZgrCDk9VIKkgQIw7yrlnHgrhuchtpdl7M37tggSb4MaucVsvW9cGeLN2zQFbtOgnXpsHhDTlZQaq7yLB1Otp5LFlf9mB0q01W9UFFMoYYU4J3RjKl+onRbyTDvUu102/lwvm10RL575kwUi0gNxGkmtpt9BjG/HC4/WCasCFMVljvedqADcqxn3PaoN5fXO0//sQBa/ffXIbt4IatuItrCMO2QSJ72gEId1y1AciwSimqpowV3TAUYALTtC0gFrmtMS9StA1JoLBRDSr9hiTaJST5fL7NFjNZyR71nn2bVrtB/cKj4fPo+HOkpl549Ol5BI3j86jdQjAzt4ui+f6dpUZRV1uj1oZImjmo0AcYFS6ibaAjKtrvNOwr0GkXfA+HEBzIgRACmtrYMLrhhERX77SQrcOI7jskyJ9VetlmtCj79gqm5AsudkdlFaBrQlkF8FdsC681llkjrvV256DbVeN7G4+1qenFQR9mJOqyTPTkRiIUN9wfexzqAw2U6teohjgvZvucQJdTZJXa3sdo7ZtvDbOzBpmYRTOxXYr1kTdYB515JWL22xXA6sa9GOJ7r3p57UTrxr3QZvYzFCnBst/ygLf/Aw==
diff --git a/docs/diagrams/StartActivityDiagram.drawio b/docs/diagrams/StartActivityDiagram.drawio
new file mode 100644
index 00000000000..4908e441e06
--- /dev/null
+++ b/docs/diagrams/StartActivityDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/StopSequenceDiagram.drawio b/docs/diagrams/StopSequenceDiagram.drawio
new file mode 100644
index 00000000000..d6fd725e18e
--- /dev/null
+++ b/docs/diagrams/StopSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/Storage.drawio b/docs/diagrams/Storage.drawio
new file mode 100644
index 00000000000..f2301f2bbad
--- /dev/null
+++ b/docs/diagrams/Storage.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/SummaryCommandSequenceDiagram.drawio b/docs/diagrams/SummaryCommandSequenceDiagram.drawio
new file mode 100644
index 00000000000..c6c9496349d
--- /dev/null
+++ b/docs/diagrams/SummaryCommandSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/SummaryPanelClassDiagram.drawio b/docs/diagrams/SummaryPanelClassDiagram.drawio
new file mode 100644
index 00000000000..767da7d3047
--- /dev/null
+++ b/docs/diagrams/SummaryPanelClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/SummarySwitchTabSequenceDiagram.drawio b/docs/diagrams/SummarySwitchTabSequenceDiagram.drawio
new file mode 100644
index 00000000000..358a5fd8af6
--- /dev/null
+++ b/docs/diagrams/SummarySwitchTabSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/TaskListClassDiagram.drawio b/docs/diagrams/TaskListClassDiagram.drawio
new file mode 100644
index 00000000000..3b6ae9f3e1e
--- /dev/null
+++ b/docs/diagrams/TaskListClassDiagram.drawio
@@ -0,0 +1 @@
+7V1Zk5u4Gv01rso8tIt9eYzd6cxUdWZyp5Obm0dsZJtpjDyAe8mvvxJILJKw8SJw0+6aiY2MBIjznW9FjPTp+uVz7G1WX6APwpGm+C8j/XakoT9bQx+45TVvsS03b1jGgZ83qWXDQ/ALkEaFtG4DHyS1HVMIwzTY1BvnMIrAPK21eXEMn+u7LWBYP+rGWwKu4WHuhXzrj8BPV3mrYypl++8gWK7okVWF/LL26M6kIVl5PnyuNOmfRvo0hjDNv61fpiDEk0fnJX15SqY/fn379z9q8Bg9fY/txfwmH+zukC7FJcQgSo8e+rP758P97J9H03oxv3/+Z33778+EdFGevHBL5otca/pKJxBE/kd8H9DWLITzx5E+QU3kRlv51l2ADqXfKmirmKVsI43hYzHvaMYmMdxGPvDJ78BH94ocCoQz+PypbJhkDeiHJxCnAbqh2aHS+PV/uPPYpJs/0aZKN25f6MjZ1ivdegnSvJuhWmT7Z7atKHS77Io3qj2/gjhYgxTEpM33klV2Cfiw+XzhC2Hwtudmkf0SuI3nYMcd0hwiNF68BOmOHXW7wCQSZgDRGcevqONziXrVIvc7BqGXBk/1U/aIpC2LvsVwX2GALkZTCCvc6JY5Vo28G+EFTWeGya+M9Kzikh9MZwdTXaU+WH713GDoS+Vay6YM+geIgfo+xKBT4FKG3QvcHOEdAdfkgWsoxwLXUNjBDNVtBVwEJe+1stsG75DsOHFNMesHcpTdJ1eIUNsOmsN0sPZ1cPnLN5x9sn5EH8E01/ugL/mEnpUUtCspHEoKLWW9BXsYZnekYLiIFHS3/KtjzdWPVmwc2RgKM9i5+MFwDuQHQzlQ3A39CNG1j+hzDK04/VCEfqWIs9sN1L/cyyWW2h1FIH+RBZhtH8sLts4ZvLbZzm44F3ANHqcVLME4XcEljLywCqg69sp97iHcEGz8A9L0lWDb26YQNa3SdVhArBCFCEaAxz666JTuMQ+9JAnmtJns1onharUEYJOOOgxsB1O9btWZ2zL3MTejG5gOcqjRvCLsdISZSj8I0w9EGOtsdIIwqxeE0UhSLYpk7o4hlagsMVcC82TEdY4Pg2EgnTinjfhw9BM7WI62R6e65q4OdQS2775PH4ucifqZay6j2RvMhHNJhd0z70pBeAtO1c2WnNoUJ5UtM1oNFioJFEllSOJs19wTK0yxRR88oa9L/PXbCmTTljyi01fCIMFnHUTon4ft7DOCxuYb+u2etON9PPT/IghTECPMFF0WMVzjgbLh1l42QnW0bCjg08HG9FTQlVXORnCCtGlGG/6aJSB+8mYhyAaip/Lht8qQs7J3ftLkvADCNj7pbZKd+wLGxW/5OMV5zWL2BNgzZeQMuW4bkFkeKRaqJBcWFesGLwyWEdoIwQJ3TTbePIiW99nWrarUhel5FaTgAe2Cuz/H3qY4GHblwMtZNASFpcV72zpNeIkcqVU1V6YpzVJS47VDgesKgLuD1Upbj7X+GrV1zaVl9Hv7TFCTQ1260GKHWjYZts0ZNbnQdYyd7DzzQV/TYYaRneBRdgJItrE4dnS9CsE95iIFVQ1SJcJ2JDlZgMoGWuvspKGfqHVP4hNV7ff225pduf03x6Wdj8WFbAy0TvRZVi+Wl6rXA/oaCei3dA2aundGXdphyrCn0Ip0pjkLeASeHxbG8s+o+4Eaa+KcK1/DeND0OI1u5e795bgPNJfdG9D8wFvDyOd8yVoYj6CxGsPrAo9W25SnKQm4liCVzpbNNMQajkBrHX6mYe+Da72DrRjy8UpltWembIPO/YHqauavk7TbWcIiglhyPe5h2KYcQtUU4XGaq1d27i8JoP2k3YgZSr+3C1kXjq1hFenhvKdrOfs8EbzFmq/dQ7p1muVkw/Qk58Q2ONrKI1wg4eCSgpe0fndpaCnO4zITmu7/SNrXge/nOAJJ8AsHzcj9IBKFhjUnI/N2V5CJ1GaTzqPCKKreqR2Ab4wvIMfItOsGF626OpV2NG1salXDTq/bT+7Yqo8JF4sESDHgtX5SoYXzqZlVwd8p9j2ondbJ9lMDCA1AYdI1qinJ4LcZA97pwICnsjVEZmmovSiYRbPcM4UvEZVwVXxjxoqRyB6CJI498WZIVL15OrJRAxIh/eUjmmYmxVL5hbvdyXOwDr3M8lzAKKVkpFTu+xzdAay9uRufYgqazFdB6N97r3CL7xMycOePdGuygnHwCw3r1WxiwlW6VdvjAfckh86QBL7Sm68WTfdekpJ95jAMvU0S5JDBu6yRiAbRBKYpXNOBavS5o6gO918gu3sKQxhnU6N7SG9knJnvWfnFdbEmwb+Q2bur97xzpp+mUzKllfZF9ofal7HnB6D8jdj+G2oqPeSJIXqm5Cj3QUQvdQ7XOLea/bzEmdZR1duVkB/i0tkmnxzSldITreWHrB35IXLIv7H0R8sQlMdU2WIBp2U+SmNUuofzeZGXgglGQyJFOkWZKn1E86n6R/S1nq6kyUQspI2pRELGTNpQLIf1ZKJRtvxNZgY3QdR3EWYysEK0DaJMRlIvbaTtCZrgKeY5RODaFG2r5XbG6RtklExhhHkoyBAGkIw+Ayynu8SPKBiFkbvCT66KHGlsBe6DHi2hyLJaY5nF1tmsf/rY1K6gRZgRQD3GwJLYHqwUypqA41tmRt6oHIB0HkC6ACyhNwPhV5gEaQCrRgKv+3fhhGHehTMH87mIeWeOaZgclqQBw9Lak5ysHDgNnNSAgcsZkDk6RaS2hPErLnlQcpahTYPjkrYsUTVjNGnIsNsjQx5liB47IMh42M5w0U1SQYZY/6Adl/XinoHqosvCj+tcAH74gFNutKy9R8D4EBUccd7F0IBSAYBxCeaJSuPFvYLFFoCF1sPlnwH2Exe4Xq0smKOf1AH9bwCeL90vtd+qX2rdneiXynMfBUlKgTfnCrw51XSO8R41xntURce7EO9RFxXoXm1/ybZ/UwE4dQrtlvjUm+F5GuOKYgrEvPuAe2JljKaz1Mx5LOEodcxi47I0snQNvAcLgmCXEAvStK8hKmnAWMDKp2Kb0ezEwABwKXGkPTCx+ThSxzARBZHyRx8+rTdpNU4wgzAEXjREtPSOA1XhowMdA6EpaDTHNm0QJR+wrriioRM0aLyv3zEa+PwvceInr7fIsm105Xv0wrRL8sK0o7ywzr0sU7BkisvHDopYdd2M3Z8Rf+NJOsPixOAm041/oXvhb0HBhl9j4CMop0CcpOOfIRpyyKvZJzuZOJsWzqA5Zt4DE0JXHm/yMa8cMLdb8A36WeFPK8QMDC4tzfGLBJWp9w0qPthTgmoVJD8AeHy/TPSWoWW7fUOLjxgV0HpAxziAsa7IuiRkqXTVz96gZfIBqMKF+AL9bXh1It5JKkfnl8ATOhniWLk2dCfD5ENwmIPXmYxMoQ/YYowHUNRifCl3GjARsyQgP0DTtHzaDj9DGJ8xm8F7GrmKonXX/F9T/k8aEOh92AcEWRk/ky/oyrjDewTfo+DfLcgJAjHGh1GttLi5oFj5bdD8wZpovfCHKTDOuuUPvpDrJjufdFWqlA8IKuVWGfp/X6GLY6oADWnIEdgxYuRIM+v5zABGDs0SkSrSJuicljV6+yCRhgtV4TPJHQOjec1A+gmi7RrEXqb8mwv+ynr0a7Ffpx7irfnJyfVj1x6iYC1B1WpZGuG4zYAeRrGfyQfpbj9++zRoEpVu1+95vqtlKZ80NrX46NmXv26/3w/vrh9eqdUzNiw+H9QxNviAEf9MzuUozEwZvW2F2aQQ94VapSlMR+VDqm1LTovY6HA1Jn0Kk3FSMhH501uXdRsPaYyfmh9gzPRSCmCbFgouVgXom0zFEbRsDW6Kkj8QMS5BPAkif6Bo6R0HNAnSHw7EEbFMkf2BJOnliobu0GD3bn6Lo1yj8nUH73aFjt7BoSq9G+B8WWjr7Ozl2OW6Mli7vBF75KQB+yb406xxVa2bxqIovWofiNBmS9w23LFj7T2ipgiOyNr+XRjjfE1sKRjTFbq4jDxBhEB+QeIxgEqgzuO42pg+uVK8S1WAS12AS3bxxHaSoBt1wROW+bQRvC7EQJQfwfl2GOVC4KPvH/KvzQpkb3K+URzezCNXssN7TetV76jtESFWWk2HxYf7vwZRtGP9lFNYsoDF8UT5ZldllFcyKcfOsF3uteCWYFkp8Su3jkqTmdjSqKyFzB7dahm+0Zmjd7HAIh8D5AWHvHgtWHt4meJqrZzYmqCt90wh24yANa9wmyAJWGaQFYEmO9jHZINmmwop3VgELxgyE3I+t6s03eQFW3fov7kfGeNgDqNFgIQhHs/xa/PufMTJ6AO3J/gTRvSriV8Ak/1w4+FXBtxk5XY3sxtVc8YbvFhoRa5UVq4yts+vDi91LPMhRG2s6m75x9i2xfvma7atgJBlraenila9uiLpApHkMkhi3r+k9gwkm48b8K8Xa15Oe78O37+eNl7unb5fUqpMcy6xoD6p07nnvdChzr2j8maC1TP0zV0hs6NWl7yGBgYQOTNM5u3ZLp8HQt7XwQsX7ggZOFzwTHhQ0bNydI2ULmu/RIsoDjijIL22p+GFPa91TLWAnyqrNp++4PYdaCpVIIyCioBONZXDW/tDnX6dKemxbAERdjr3fNp1sHPvcBVc/U//O/JPFH76ReTf5fRr/PRTK/iC02RvP/p7cdWdJvfeKNU1xoJQqyPKpB21KtdbyqRpIpt4TyatWpIzwAdc5S84f7DdLASntAdaHT67OlTVZdTfO87mZAQJoU61mMEX1B5RJddnXdRwn1doxKSkuihsZDXH41XREwtnLJOyOOdS1QRHFCrR7sukjBZZpiHpKdmRnqbXvu7QWCLsSQvz6Lyv+wX6IPziRd7yzDb+AIs8GtKjdDGGoyjzzlsHIcbH7yB8AngGj+HSk1lTt1nzX0RbojILuhzNgUUeSr1oT8iSF/Jkl877yLgwP0RQe1jB5yg3MEh1fv3VQVcuPZpL9T3L7vb9FgO6BsA7sP415nXgqrzqGLQZQ5hWBTj2NqtMS6HG/wM=
diff --git a/docs/diagrams/TaskListPanelClassDiagram.drawio b/docs/diagrams/TaskListPanelClassDiagram.drawio
new file mode 100644
index 00000000000..736d7de508d
--- /dev/null
+++ b/docs/diagrams/TaskListPanelClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/TimerPanelActivityDiagram.drawio b/docs/diagrams/TimerPanelActivityDiagram.drawio
new file mode 100644
index 00000000000..1e19633fb69
--- /dev/null
+++ b/docs/diagrams/TimerPanelActivityDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/UiClassDiagram.drawio b/docs/diagrams/UiClassDiagram.drawio
new file mode 100644
index 00000000000..bdc18c28af0
--- /dev/null
+++ b/docs/diagrams/UiClassDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml
index 92746f9fcf7..1e9162a90b5 100644
--- a/docs/diagrams/UiClassDiagram.puml
+++ b/docs/diagrams/UiClassDiagram.puml
@@ -11,9 +11,13 @@ Class UiManager
Class MainWindow
Class HelpWindow
Class ResultDisplay
-Class PersonListPanel
-Class PersonCard
+Class TaskListPanel
+Class TaskCard
Class StatusBarFooter
+class CalendarPanel
+class CalendarDayCard
+class ProductivityPanel
+class ProductivityCard
Class CommandBox
}
@@ -33,25 +37,37 @@ UiManager -down-> MainWindow
MainWindow --> HelpWindow
MainWindow *-down-> CommandBox
MainWindow *-down-> ResultDisplay
-MainWindow *-down-> PersonListPanel
+MainWindow *-down-> TaskListPanel
MainWindow *-down-> StatusBarFooter
+MainWindow *-down-> CalendarPanel
+MainWindow *-down-> ProductivityPanel
-PersonListPanel -down-> PersonCard
+TaskListPanel -down-> TaskCard
+CalendarPanel -down-> CalendarDayCard
+ProductivityPanel -down-> ProductivityCard
MainWindow -left-|> UiPart
ResultDisplay --|> UiPart
CommandBox --|> UiPart
-PersonListPanel --|> UiPart
-PersonCard --|> UiPart
+TaskListPanel --|> UiPart
+TaskCard --|> UiPart
+CalendarPanel --|> UiPart
+CalendarDayCard --|> UiPart
+ProductivityPanel --|> UiPart
+ProductivityCard --|> UiPart
StatusBarFooter --|> UiPart
HelpWindow -down-|> UiPart
-PersonCard ..> Model
+TaskCard ..> Model
+CalendarDayCard ..> Model
+ProductivityCard ..> Model
UiManager -right-> Logic
MainWindow -left-> Logic
-PersonListPanel -[hidden]left- HelpWindow
+ProductivityPanel -[hidden]left- CalendarPanel
+CalendarPanel -[hidden]left- TaskListPanel
+TaskListPanel -[hidden]left- HelpWindow
HelpWindow -[hidden]left- CommandBox
CommandBox -[hidden]left- ResultDisplay
ResultDisplay -[hidden]left- StatusBarFooter
diff --git a/docs/diagrams/UndoRedoState0.drawio b/docs/diagrams/UndoRedoState0.drawio
new file mode 100644
index 00000000000..9bb19a625e0
--- /dev/null
+++ b/docs/diagrams/UndoRedoState0.drawio
@@ -0,0 +1 @@
+3VdRb5swEP41PGYCDCR5TEjZOmnTpGjqtDcHHHBncGZMk+7X7wAbcCDtNqXV1DxE5rvz2f6+485YKMxP7wU+ZJ94Qpjl2snJQhvLdYPAh/8aeGwBzwtaIBU0aSGnB7b0F1GgrdCKJqQ0HCXnTNKDCca8KEgsDQwLwY+m254zc9UDTskI2MaYjdE7msisRRfuvMc/EJpmemUnWLaWHGtndZIywwk/DiB0Y6FQcC7bUX4KCau507y086IL1m5jghTyTyZsZ8nma3S3S7/7t/dREaSf0beZivKAWaUOrDYrHzUDgldFQuogtoXWx4xKsj3guLYeQXLAMpkzeHJgqMIRIcnp4j6d7vSQNYTnRIpHcFETkO+1U1TGOJrAY88/0lmUDbifKz+sJE+70D0rMFDE/AVJ7oik24JKiuuJW4klGXEGp5cmMaUU/AcJOeMCkIIX4LneU8bOIMxoWsBjDGwRwNc1lxTycaUMOU2SeplJJUytriCGt7ANMRZjLTQ0lMJ9KSnQRL4GrOZ6B4O0HjSKlBqGVTrL25XJt02Zpt4Z7zV1Ci7qVGk17ndw+NVHwg4ZXkMR7AWrLgo2UGooiuWiKIoWm/VIQbDYze9KtUlXd82zP+Z5OcEzeimel8/Xb1Ikq7oR1tnKcFnS+KmUB8LC0CCMJKMOeUYXtGQsUiKfy4cxrQPa/AnaNCYIw5I+mNuY4lKt8IVT2GBfxByzo4zkKHklYqJmDVvoWSDkzd/ZaG57C4SWCw/NfTOufRa3pWUUt1G6Y+Hfxdd3pP+qe581jI7rgdTz16xEztQVpy01e96I27MV/Ky4NszK5i66AgfHPpx6oy5OYSUaUuoAzR2gq19t3Lfec0bZP6H0le4G8Njfk9u3p//YQDe/AQ==
diff --git a/docs/diagrams/UndoRedoState1.drawio b/docs/diagrams/UndoRedoState1.drawio
new file mode 100644
index 00000000000..ead3fb1458f
--- /dev/null
+++ b/docs/diagrams/UndoRedoState1.drawio
@@ -0,0 +1 @@
+3Zddb5swFIZ/DZeRAAMhlwlt9iFtmhRNnXbnYgfcGZwZ06T79TsONh+FLN2UVl17UcFr+9h+Xvtw4qCkOLyTeJd/EoRyx3fJwUFXju9HUQj/tfDQCEEQNUImGWkkrxM27Bc1omvUmhFaDToqIbhiu6GYirKkqRpoWEqxH3bbCj6cdYczOhI2KeZj9YYRlTdq7M87/T1lWW5n9qJF01Jg29nspMoxEfuehK4dlEghVPNUHBLKNTvLpRm3PtHaLkzSUj1lwGZGrr6ub26z7+GHu3UZZZ/Rt5mJco95bTZsFqseLAEp6pJQHcR10GqfM0U3O5zq1j1YDlquCg5vHjyacFQqeji5Tq/dPZwaKgqq5AN0MQNQGDRDzInxLMB9xx/ZU5T32M9NP2wsz9rQHRV4MGD+ApI/grTcKiqPp64ocEkcvcToZ62tXMEFoIqCFHbaCCrgUUNylZLiB00EFxKUUpTQc7VlnD+SMGdZCa8p4IQ1oJWGzeDALk1DwQjR00xaNTTzAm4F1h3jVjw2q70BfbP85zILTZzoiGvYt/CQ6YeNwgpyipFhlrbl7foUukOfpm5V8JI+RSd9qq0bd7ew+eVHync5XsE96gyrTxrWc6pviuOj9XodX61GDkKLe/y7UPay+d9yDsecFxOc0XNxnj+Fs/ffcQ5i93VxXpz/ktKSLHVJorMCx1XF0j+lFgCWJANglIxqlbO4ejjCCRxWk5Rjxe6H4acYmRm+CAYTd9nFH36zR5grUcuUmlH9IuVMIC9+FEhhmVE1CnS0rN32v7toy87XVBAFC3cabs/b+Uumbm+qamxyxlYc3exo2QpIN8yqY3m/hA6euzv0y6MmyyS1PELRAbCuodpE1MR96x/pIA7POh1fxml47X56NLen+/2Grn8D
diff --git a/docs/diagrams/UndoRedoState2.drawio b/docs/diagrams/UndoRedoState2.drawio
new file mode 100644
index 00000000000..807bcdd1ecc
--- /dev/null
+++ b/docs/diagrams/UndoRedoState2.drawio
@@ -0,0 +1 @@
+3Vddb5swFP01PEYCHEjymNCyD2nTpGjqtDcXO+DO4MyYJt2v33Ww+Qik6aY2ahuJyD7XvrbPMfdeHBTl+w8Sb7MvglDu+C7ZO+jK8f0wDOBfAw81MJ2GNZBKRmrIa4E1+0MN6Bq0YoSWvYFKCK7Ytg8moihoonoYllLs+sM2gvdX3eKUDoB1gvkQvWFEZTU692ct/pGyNLMre+GituTYDjYnKTNMxK4DoWsHRVIIVbfyfUS55s7yUs+LT1ibjUlaqKdMWE/I1ff45jb9GXy6i4sw/Yp+TIyXe8wrc2CzWfVgGZCiKgjVTlwHrXYZU3S9xYm27kBywDKVc+h50DTuqFR0f3KfXnN6uDVU5FTJBxhiJqBgWk8xN8azBO5a/pG9RVmH+5kZh43kaeO6ZQUahph/IMkfkLTcKCoPty7PcUEcvcXwd6WlXGGi+/DEy7JkaZHrczfWAb1AlOpzWCopftFIcCEBKUQBI1cbxvkRhDl4h24CC8Bu0ErTzuDqLo0hZ4ToZUZF68v6DLpNrU5Gt/lQtuZd6Mrmv5RsaORuh1yTfQuNVDfWCiuILgaGVRrL+9UpcPs6jb1f00vqFJ7UqbJq3N3C4ZefKd9meCVUR7DqpGAdpbqiOD6K43h+tRooCBb38HumOGYzgeU5GPK8GOEZvRTPs6fw7L05nqdz93XxvDifU2lBlro40VGBY0gTyWOhBQiLoh5hlAyqlrN0degIRuiwmKQcK3bfdz/GkVnhm2A6v1k1QtTP3gOaS1HJhJpZ3XLljCNvfuRIYZlSNXB0kKw59v+raAvQ11QahUehuyG3o+3skqHbG6sf65ixEQc1W7ZsBaQNk/JQ6C9hgOdu993yqI4yUSUPpGgHkKI7gaj2++6T9CI4q/T8okoPi+CR7OG/uewRLC6WPaDbfu3VYar9ZEbXfwE=
diff --git a/docs/diagrams/UndoRedoState3.drawio b/docs/diagrams/UndoRedoState3.drawio
new file mode 100644
index 00000000000..a3b5faeed3b
--- /dev/null
+++ b/docs/diagrams/UndoRedoState3.drawio
@@ -0,0 +1 @@
+3Zddb5swFIZ/DZeRAAMhlwlt9iFtmhRNnXbnYgfcGZwZ0yT79TsOdoBCmm5qo7a5iMxr+xg/r3N84qCk2H2QeJN/EYRyx3fJzkFXju9HUQjfWtg3QhBEjZBJRhrJa4UV+0ON6Bq1ZoRWvYFKCK7Ypi+moixpqnoallJs+8PWgvdX3eCMDoRVivlQvWFE5Y0a+9NW/0hZltuVvWjW9BTYDjY7qXJMxLYjoWsHJVII1bSKXUK5Zme5NPOWJ3qPLyZpqZ4yYTUhV9+XN7fZz/DT3bKMsq/ox8REuce8Nhs2L6v2loAUdUmoDuI6aLHNmaKrDU517xYsBy1XBYcnD5omHJWK7k6+p3fcPZwaKgqq5B6GmAkoDJop5sR4FuC25Y/sKco77KdmHDaWZ8fQLRVoGDD/AMkfQJqvFZWHU1cUuCSOfsXod62tXAAt0T4NcAIY1WdWKSl+0URwIUEpRQkjF2vG+QMJc5aV8JgCSFgdLTRmBkd1bjoKRoheZtSkvo3P4FNgfTE+xUObjme/a5P/UjahkbMccQ37FhqZbqwUVpBNjAyrHHver0+h2/dp7PcUXNKn6KRPtXXj7hY2P/9M+SbHC/gdtYbVJw3rONU1xfHRcrmMrxYDB6HHPXyeKW/ZzG85h0POsxHO6KU4T5/C2XtznIPYfV2cZ+fvUFqSuS5GdFbguKpY+lhqAWBJ0gNGyaBKOYurgyMcwWE1STlW7L4ffoyRWeGbYLBwm138/m09wFyJWqbUzOqWJ2cCefGDQArLjKpBoINlx23/v4u24HxNpVAwc8fhdrydXjJ1e2P1YpMz1uLgZkvLVkC6Y1IdCvs5DPDcza5bHjVZJqnlAYoOAFd0JxE1cd/7JR3E4Vmn44s6PSx6R24P/83dHuHsYrcHPLb/7po01f5FRtd/AQ==
diff --git a/docs/diagrams/UndoRedoState4.drawio b/docs/diagrams/UndoRedoState4.drawio
new file mode 100644
index 00000000000..2c164e0a409
--- /dev/null
+++ b/docs/diagrams/UndoRedoState4.drawio
@@ -0,0 +1 @@
+3Zddb5swFIZ/DZeRAAMhlwlt9iFtmhRNnXbnYgfcGZwZ0yT79TsOdoBCmm5qo7a5iMxr+xg/r3N84qCk2H2QeJN/EYRyx3fJzkFXju9HUQjfWtg3QhBEjZBJRhrJa4UV+0ON6Bq1ZoRWvYFKCK7Ypi+moixpqnoallJs+8PWgvdX3eCMDoRVivlQvWFE5Y0a+9NW/0hZltuVvWjW9BTYDjY7qXJMxLYjoWsHJVII1bSKXUK5Zme5NPOWJ3qPLyZpqZ4yYTUhV9+XN7fZz/DT3bKMsq/ox8REuce8Nhs2L6v2loAUdUmoDuI6aLHNmaKrDU517xYsBy1XBYcnD5omHJWK7k6+p3fcPZwaKgqq5B6GmAkoDJop5sR4FuC25Y/sKco77KdmHDaWZ8fQLRVoGDD/AMkfQJqvFZWHU1cUuCSOfsXod62tXHBWqfZpgBPAqD6zSknxiyaCCwlKKUoYuVgzzh9ImLOshMcUQMLqaKExMziqc9NRMEL0MqMm9W18Bp8C64vxKR7adDz7XZv8l7IJjZzliGvYt9DIdGOlsIJsYmRY5djzfn0K3b5PY7+n4JI+RSd9qq0bd7ew+flnyjc5XgjVMaw+aVjHqa4pjo+Wy2V8tRg4CD3u4fNMectmfss5HHKejXBGL8V5+hTO3pvjHMTu6+I8O3+H0pLMdTGiswLHVcXSx1ILAEuSHjBKBlXKWVwdHOEIDqtJyrFi9/3wY4zMCt8Eg4Xb7OL3b+sB5krUMqVmVrc8ORPIix8EUlhmVA0CHSw7bvv/XbQF52sqhYKZOw634+30kqnbG6sXm5yxFgc3W1q2AtIdk+pQ2M9hgOdudt3yqMkySS0PUHQAuKI7iaiJ+94v6SAOzzodX9TpYdE7cnv4b+72CGcXuz3gsf1316Sp9i8yuv4L
diff --git a/docs/diagrams/UndoRedoState5.drawio b/docs/diagrams/UndoRedoState5.drawio
new file mode 100644
index 00000000000..3ca60472af1
--- /dev/null
+++ b/docs/diagrams/UndoRedoState5.drawio
@@ -0,0 +1 @@
+5VjbcpswEP0aHpPhbvvRJqGXmTad8XTS6ZuMZFAiEJVF7PTruwJxMzhO08STpH7wiCNpJZ2z2l0wnCDdfRAoT75wTJhhm3hnOBeGbbu2B/8KuNeAZVdALCiuIKsFlvQ30aCp0YJisukNlJwzSfM+GPEsI5HsYUgIvu0PW3PWXzVHMRkAywixIXpNsUwqdGpPWvwjoXFSr2z5s6onRfVgfZJNgjDfdiDn0nACwbmsWukuIExxV/NSzQsP9DYbEySTj5mwPMMX38PrVfzT+3QTZn781flxpq3cIVboA+vNyvuaAcGLDBNlxDScxTahkixzFKneLUgOWCJTBk8WNLU5IiTZHdyn1ZwevIbwlEhxD0P0BMdzqynaY6yawG3Lv+P6FZZ0uJ/ocUhLHjemW1agoYn5C5LsAUnztSSi9Lo0RRk21Bb9X4WSchExgkT7OOATmJF90jZS8FsScMYFIBnPYORiTRnbgxCjcQaPETAJyzsLxTMFX53rjpRirJYZVamv4zMI5dbCaKGmQ50a5+/qZL+UTs6IM/tMkb2CRqwaS4kkhBMNwypNz/vVyTP7Oo1dKPeUOvkHdSpqNW5WcPj5Z8LyBC3gHrWCFQcF6yjVFcWwnTAMpxeLgYLQY5a/ZwpcdeivefaGPM9GeHZeiufJY3i23hzP7tR8XTzPjidRkuG5qkZUVGBos6HRQ6EFCAuCHmEED8qUo3R16PBG6KgxQRiS9K5vfowjvcI3TmHhRg3f6afrAc0bXoiI6Fnd+uSIIWu6Z0giERM5MFRK1hz76SrWFedrqoX8vdDdkNvRdnLK0G2NFYxVzFjzUs2WrboCUh1nm7Kyn8MAy8x33fKoijJBIUpSlAFI0Z1AVNl990l65h1VenpSpYdV70j2sN9c9vBmryx7WGNl6x5p8O6Yk9J35SGP7PC6QtFtXHroVSEZVe5e4hiJ2yuYRaU6u3lueg9mnn15pmFol/JUL+mw7+eJcd5ejDOHgljWSV3f/fcgZ40FuWUV2kx1b2wTE0Ykwef/XazzvclRxceu4BMEh8f2C0tVKbSfqZzLPw==
diff --git a/docs/diagrams/UndoSequenceDiagram.drawio b/docs/diagrams/UndoSequenceDiagram.drawio
new file mode 100644
index 00000000000..4727f48a814
--- /dev/null
+++ b/docs/diagrams/UndoSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/UndoSequenceDiagram.puml
index 410aab4e412..27cfca50de7 100644
--- a/docs/diagrams/UndoSequenceDiagram.puml
+++ b/docs/diagrams/UndoSequenceDiagram.puml
@@ -3,42 +3,42 @@
box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":JelphaBotParser" as JelphaBotParser LOGIC_COLOR
participant "u:UndoCommand" as UndoCommand LOGIC_COLOR
end box
box Model MODEL_COLOR_T1
participant ":Model" as Model MODEL_COLOR
-participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR
+participant ":VersionedJelphaBot" as VersionedJelphaBot MODEL_COLOR
end box
[-> LogicManager : execute(undo)
activate LogicManager
-LogicManager -> AddressBookParser : parseCommand(undo)
-activate AddressBookParser
+LogicManager -> JelphaBotParser : parseCommand(undo)
+activate JelphaBotParser
create UndoCommand
-AddressBookParser -> UndoCommand
+JelphaBotParser -> UndoCommand
activate UndoCommand
-UndoCommand --> AddressBookParser
+UndoCommand --> JelphaBotParser
deactivate UndoCommand
-AddressBookParser --> LogicManager : u
-deactivate AddressBookParser
+JelphaBotParser --> LogicManager : u
+deactivate JelphaBotParser
LogicManager -> UndoCommand : execute()
activate UndoCommand
-UndoCommand -> Model : undoAddressBook()
+UndoCommand -> Model : undoJelphaBot()
activate Model
-Model -> VersionedAddressBook : undo()
-activate VersionedAddressBook
+Model -> VersionedJelphaBot : undo()
+activate VersionedJelphaBot
-VersionedAddressBook -> VersionedAddressBook :resetData(ReadOnlyAddressBook)
-VersionedAddressBook --> Model :
-deactivate VersionedAddressBook
+VersionedJelphaBot -> VersionedJelphaBot :resetData(ReadOnlyJelphaBot)
+VersionedJelphaBot --> Model :
+deactivate VersionedJelphaBot
Model --> UndoCommand
deactivate Model
diff --git a/docs/diagrams/UseCaseDiagram.drawio b/docs/diagrams/UseCaseDiagram.drawio
new file mode 100644
index 00000000000..bb7f31c0e8c
--- /dev/null
+++ b/docs/diagrams/UseCaseDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/ViewTaskListGetSequenceDiagram.drawio b/docs/diagrams/ViewTaskListGetSequenceDiagram.drawio
new file mode 100644
index 00000000000..126b62a9339
--- /dev/null
+++ b/docs/diagrams/ViewTaskListGetSequenceDiagram.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/CommitActivityDiagram.puml b/docs/diagrams/add-remark/CommitActivityDiagram.puml
similarity index 100%
rename from docs/diagrams/CommitActivityDiagram.puml
rename to docs/diagrams/add-remark/CommitActivityDiagram.puml
diff --git a/docs/diagrams/addReminder.drawio b/docs/diagrams/addReminder.drawio
new file mode 100644
index 00000000000..83a46a97ed9
--- /dev/null
+++ b/docs/diagrams/addReminder.drawio
@@ -0,0 +1 @@
+5Vhdc6IwFP01PtoRwoc8VlvbrdNOx3a27r7sRAiQbSAYouL++g0QkC9Hbe3OdpcHzT0JN9xz7s1l6IFxkNwwGPn31EGkpw6cpAeueqpqqbr4TYFtDhhAzQGPYSeHlB3whH8hCQ4kusIOimsLOaWE46gO2jQMkc1rGGSMburLXErqu0bQQy3gyYakjb5gh/s5OlTNHX6LsOcXOyuGlc8EsFgsI4l96NBNBQLXPTBmlPJ8FCRjRFLuCl7y+yZ7ZssHYyjkx9yAl/HmNQlu7tz5cmqpLnbdaV/RcjdrSFYyYvm0fFtQwOgqdFDqZdADo42POXqKoJ3OboTmAvN5QISliKGLCRlTQll2LxiLayKeaBRzRl9RZcawh2jhipl2HDK0NWIcJRVIxnWDaIA424olxexQciyTTDelvdlJZugS8ytygQKEMk280veOSTGQZJ5ArNrBq0HEtqOFGHjpIHYKSOxQouIfBimp4SKOMnvQhDzExzQIYOjMULwSHpqKiVSL0uEqIBMGA3SEbDTksvgUkC6XxKV1KBYWlIlqBiNIsBcKwxaCIfYvKDh5nioasub2vR64DwszIV+jfkdlgMsZCrAoBib5f2etCNInMMAkDfoWkTXi2IbtIjLE1V1EY1PEP5CuKribXQ1dzfNIpep1qQzQlqo8vqtSGR+llN6l1B0ikQ9HtF0d/4FGZflIjUylrZHSVU4fppF5uM+g0LlMO7awQhqmh5YDYz8TSqmLspch5NS6eZufSvxd4RcYQwRyvK6/A3RxInd4pFg8SUk/0Kwa/ZbaoDWmK2YjeVe1Zx9wZDYdcchEN2g5yiQqw367akpXG9svm01gHGO7LpbQiG3nabVdZO0js7/J6suMq6RmbaX116usDy6shj7aG4XWDeugr/NpvV7+BF9AssWTWTRYar7l+XZf6ThGT9W6VrDVc834BHoajcY21JS3iQkOOTqfktvX6ffnH3cbzwsXswV4MR6fH/rKYSHf805ftro9XalD472NytD0etJ3vPd1vUuYZ+hTndydduAd1aca6X0UPX8o4zXrosjN97aqDl/DjzvBOrUDnyfvgabVqDKs4/IenJ73wtx9ZMip3n2pAde/AQ==
diff --git a/docs/diagrams/getCommandResultReferenceDiagram.drawio b/docs/diagrams/getCommandResultReferenceDiagram.drawio
new file mode 100644
index 00000000000..210e075b8ed
--- /dev/null
+++ b/docs/diagrams/getCommandResultReferenceDiagram.drawio
@@ -0,0 +1 @@
+5Vhdc6IwFP01PtoRwoc8VlvbrdNOx3a27r7sRAiQbSAYouL++g0QkC9Hbe3OdpcHzT0JN9xz7s1l6IFxkNwwGPn31EGkpw6cpAeueqpqqbr4TYFtDhhAzQGPYSeHlB3whH8hCQ4kusIOimsLOaWE46gO2jQMkc1rGGSMburLXErqu0bQQy3gyYakjb5gh/s5OlTNHX6LsOcXOyuGlc8EsFgsI4l96NBNBQLXPTBmlPJ8FCRjRFLuCl7y+yZ7ZssHYyjkx9yAl/HmNQlu7tz5cmqpLnbdaV/RcjdrSFYyYvm0fFtQwOgqdFDqZdADo42POXqKoJ3OboTmAvN5QISliKGLCRlTQll2LxiLayKeaBRzRl9RZcawh2jhipl2HDK0NWIcJRVIxnWDaIA424olxexQciyTTDelvdlJZugS8ytygQKEMk280veOSTGQZJ5ArNrBq0HEtqOFGHjpIHYKSOxQouIfBimp4SKOMnvQhDzExzQIYOjMULwSHpqKiVSL0uEqIBMGA3SEbDTksvgUkC6XxKV1KBYWlIlqBiNIsBcKwxaCIfYvKDh5nioasub2vR64DwszIV+jfkdlgMsZCrAoBib5f2etCNInMMAkDfoWkTXi2IbtIjLE1V1EY1PEP5CuKribXQ1dzfNIpep1qQzQlqo8vqtSGR+llN6l1B0ikQ9HtF0d/4FGZflIjUylrZHSVU4fppF5uM+g0LlMO7awQhqmh5YDYz8TSqmLspch5NS6eZufSvxd4RcYQwRyvK6/A3RxInd4pFg8SUk/0Kwa/ZbaoDWmK2YjeVe1Zx9wZDYdcchEN2g5yiQqw367akpXG9svm01gHGO7LpbQiG3nabVdZO0js7/J6suMq6RmbaX116usDy6shj7aG4XWDeugr/NpvV7+BF9AssWTWTRYar7l+XZf6ThGT9W6VrDVc834BHoajcY21JS3iQkOOTqfktvX6ffnH3cbzwsXswV4MR6fH/rKYSHf805ftro9XalD472NytD0etJ3vPd1vUuYZ+hTndydduAd1aca6X0UPX8o4zXrosjN97aqDl/DjzvBOrUDnyfvgabVqDKs4/IenJ73wtx9ZMip3n2pAde/AQ==
diff --git a/docs/diagrams/interaction.drawio b/docs/diagrams/interaction.drawio
new file mode 100644
index 00000000000..9375163ceee
--- /dev/null
+++ b/docs/diagrams/interaction.drawio
@@ -0,0 +1 @@
+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
diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/old/ArchitectureDiagram.puml
similarity index 100%
rename from docs/diagrams/ArchitectureDiagram.puml
rename to docs/diagrams/old/ArchitectureDiagram.puml
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/old/ArchitectureSequenceDiagram.puml
similarity index 94%
rename from docs/diagrams/ArchitectureSequenceDiagram.puml
rename to docs/diagrams/old/ArchitectureSequenceDiagram.puml
index d1e2ae93675..a707426cab6 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/old/ArchitectureSequenceDiagram.puml
@@ -13,7 +13,7 @@ activate ui UI_COLOR
ui -[UI_COLOR]> logic : execute("delete 1")
activate logic LOGIC_COLOR
-logic -[LOGIC_COLOR]> model : deletePerson(p)
+logic -[LOGIC_COLOR]> model : deleteTask(t)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/old/DeleteSequenceDiagram.puml
similarity index 67%
rename from docs/diagrams/DeleteSequenceDiagram.puml
rename to docs/diagrams/old/DeleteSequenceDiagram.puml
index 1dc2311b245..1e814359940 100644
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ b/docs/diagrams/old/DeleteSequenceDiagram.puml
@@ -3,7 +3,7 @@
box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":JelphaBotParser" as JelphaBotParser LOGIC_COLOR
participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR
participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR
@@ -16,17 +16,17 @@ end box
[-> LogicManager : execute("delete 1")
activate LogicManager
-LogicManager -> AddressBookParser : parseCommand("delete 1")
-activate AddressBookParser
+LogicManager -> JelphaBotParser : parseCommand("delete 1")
+activate JelphaBotParser
create DeleteCommandParser
-AddressBookParser -> DeleteCommandParser
+JelphaBotParser -> DeleteCommandParser
activate DeleteCommandParser
-DeleteCommandParser --> AddressBookParser
+DeleteCommandParser --> JelphaBotParser
deactivate DeleteCommandParser
-AddressBookParser -> DeleteCommandParser : parse("1")
+JelphaBotParser -> DeleteCommandParser : parse("1")
activate DeleteCommandParser
create DeleteCommand
@@ -36,23 +36,26 @@ activate DeleteCommand
DeleteCommand --> DeleteCommandParser : d
deactivate DeleteCommand
-DeleteCommandParser --> AddressBookParser : d
+DeleteCommandParser --> JelphaBotParser : d
deactivate DeleteCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
-DeleteCommandParser -[hidden]-> AddressBookParser
+DeleteCommandParser -[hidden]-> JelphaBotParser
destroy DeleteCommandParser
-AddressBookParser --> LogicManager : d
-deactivate AddressBookParser
+JelphaBotParser --> LogicManager : d
+deactivate JelphaBotParser
LogicManager -> DeleteCommand : execute()
activate DeleteCommand
-DeleteCommand -> Model : deletePerson(1)
+DeleteCommand -> Model : deleteTask(1)
activate Model
Model --> DeleteCommand
deactivate Model
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+Model -[hidden]-> DeleteCommand
+destroy Model
create CommandResult
DeleteCommand -> CommandResult
diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/old/LogicClassDiagram.puml
similarity index 98%
rename from docs/diagrams/LogicClassDiagram.puml
rename to docs/diagrams/old/LogicClassDiagram.puml
index 016ef33e2e2..c0c5a07c9db 100644
--- a/docs/diagrams/LogicClassDiagram.puml
+++ b/docs/diagrams/old/LogicClassDiagram.puml
@@ -8,7 +8,7 @@ package Logic {
package Parser {
Interface Parser <>
-Class AddressBookParser
+Class JelphaBotParser
Class XYZCommandParser
Class CliSyntax
Class ParserUtil
diff --git a/docs/diagrams/old/StartSequenceDiagram.puml b/docs/diagrams/old/StartSequenceDiagram.puml
new file mode 100644
index 00000000000..2b9376eb3a8
--- /dev/null
+++ b/docs/diagrams/old/StartSequenceDiagram.puml
@@ -0,0 +1,69 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":JelphaBotParser" as JelphaBotParser LOGIC_COLOR
+participant ":StartCommandParser" as StartCommandParser LOGIC_COLOR
+participant "d:StartCommand" as StartCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("delete 1")
+activate LogicManager
+
+LogicManager -> JelphaBotParser : parseCommand("start 1")
+activate JelphaBotParser
+
+create StartCommandParser
+JelphaBotParser -> StartCommandParser
+activate StartCommandParser
+
+StartCommandParser --> JelphaBotParser
+deactivate StartCommandParser
+
+JelphaBotParser -> StartCommandParser : parse("1")
+activate StartCommandParser
+
+create StartCommand
+StartCommandParser -> StartCommand
+activate StartCommand
+
+StartCommand --> StartCommandParser : d
+deactivate StartCommand
+
+StartCommandParser --> JelphaBotParser : d
+deactivate StartCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+StartCommandParser -[hidden]-> JelphaBotParser
+destroy StartCommandParser
+
+JelphaBotParser --> LogicManager : d
+deactivate JelphaBotParser
+
+LogicManager -> StartCommand : execute()
+activate StartCommand
+
+StartCommand -> Model : startTask(1)
+activate Model
+
+Model --> StartCommand
+deactivate Model
+
+create CommandResult
+StartCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> StartCommand
+deactivate CommandResult
+
+StartCommand --> LogicManager : result
+deactivate StartCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/old/StopSequenceDiagram.puml b/docs/diagrams/old/StopSequenceDiagram.puml
new file mode 100644
index 00000000000..fd02bc151d8
--- /dev/null
+++ b/docs/diagrams/old/StopSequenceDiagram.puml
@@ -0,0 +1,69 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":JelphaBotParser" as JelphaBotParser LOGIC_COLOR
+participant ":StopCommandParser" as StopCommandParser LOGIC_COLOR
+participant "d:StopCommand" as StopCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("delete 1")
+activate LogicManager
+
+LogicManager -> JelphaBotParser : parseCommand("stop 1")
+activate JelphaBotParser
+
+create StopCommandParser
+JelphaBotParser -> StopCommandParser
+activate StopCommandParser
+
+StopCommandParser --> JelphaBotParser
+deactivate StopCommandParser
+
+JelphaBotParser -> StopCommandParser : parse("1")
+activate StopCommandParser
+
+create StopCommand
+StopCommandParser -> StopCommand
+activate StopCommand
+
+StopCommand --> StopCommandParser : d
+deactivate StopCommand
+
+StopCommandParser --> JelphaBotParser : d
+deactivate StopCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+StopCommandParser -[hidden]-> JelphaBotParser
+destroy StopCommandParser
+
+JelphaBotParser --> LogicManager : d
+deactivate JelphaBotParser
+
+LogicManager -> StopCommand : execute()
+activate StopCommand
+
+StopCommand -> Model : startTask(1)
+activate Model
+
+Model --> StopCommand
+deactivate Model
+
+create CommandResult
+StopCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> StopCommand
+deactivate CommandResult
+
+StopCommand --> LogicManager : result
+deactivate StopCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/UndoRedoState0.puml b/docs/diagrams/old/UndoRedoState0.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState0.puml
rename to docs/diagrams/old/UndoRedoState0.puml
diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/old/UndoRedoState1.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState1.puml
rename to docs/diagrams/old/UndoRedoState1.puml
diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/old/UndoRedoState2.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState2.puml
rename to docs/diagrams/old/UndoRedoState2.puml
diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/old/UndoRedoState3.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState3.puml
rename to docs/diagrams/old/UndoRedoState3.puml
diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/old/UndoRedoState4.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState4.puml
rename to docs/diagrams/old/UndoRedoState4.puml
diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/old/UndoRedoState5.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState5.puml
rename to docs/diagrams/old/UndoRedoState5.puml
diff --git a/docs/diagrams/saveJelphaBotReferenceDiagram.drawio b/docs/diagrams/saveJelphaBotReferenceDiagram.drawio
new file mode 100644
index 00000000000..9dc3157870e
--- /dev/null
+++ b/docs/diagrams/saveJelphaBotReferenceDiagram.drawio
@@ -0,0 +1 @@
+7Zrdc9soEMD/Gs9cH+KR0Pdj4sTpJNObm3Onlz4SCVtckXAR/upff2AhW+ijlh3b5zbOQwILQmJ/u8suk541SJaPDE7jTzRCpAeMaNmz7nsABMARv6VglQtsx8sFE4ajXGRuBSP8AymhoaQzHKFMm8gpJRxPdWFI0xSFXJNBxuhCnzamRH/rFE5QTTAKIalL/8ERj3OpD7yt/CPCk7h4s+kG+UgCi8lqJ1kMI7ooiayHnjVglPK8lSwHiEjdFXrJnxu2jG4+jKGUd3kAf88W35bJ49P45ftzAMZ4PH6+Me18mTkkM7Vj9bV8VaiA0VkaIbmK0bPuFjHmaDSFoRxdCOZCFvOEiJ4pmmNMyIASytbPWsPhYBAEQl7/WrWBOWIcLUsi9fWPiCaIs5WYUtiSUqSyJKfoL7ZcvMJs4hITy1FCqGxhsll6qy7RUBrbQ3ugQXkuEa+9exWNiWxkUSESb9hIxV+YSM2lr9l03TeqogzO0ROaxvBOGEgVibClqWzOEjJkMEEduNCUK+8yLTldKU06mphYqEu4q3UHCZ6kohMKVoj9BvCGn59NGwUv4ScnGf/56i3Jl+lNg+VbtyNOmYwIb/MBoeshTDCRm/2IyBxxHMK6c4yh6xtyvYwz+g2VRgae2Lehlio/sf6p4PSOQ8h0dUSuFfSD8k8NWNDAyz0VLqcJ11NG0ydEci95x+zA3uxM/5zw3DZ4I8SwCDc/4CtBf6MEC1BsA/Q9krRtnaQHdpEEvnNGkt7ufAGl0a3MvEQvpak8myKYxWtspo5IqImtXiTOvlN0v5bH7peKdd5bqV6rnlGkZXN1LZf05jQ4QCFjiECO53oO2KRL9Ya/KBZfsg2lga9BDOwKjozOWIjUU+Wcrb5QH9i6QRiVtThkE8Rra63pbnZ+OHD/Cnw3cMs2dUjVrKUrcLFQ3w7+V+CmeSXehTg4jotL4p7u4r5/ZuJNdUw78ZDALMNhK2eggTYOBZ1v+mefbVyURQCjcnIfGgNsU1/IP3cAsGrmkBejm7RM1bisKGf/+LcY+1AzHJH3cN1U9DxLxY9yUqZEtTJUZlEihSO3aiDBUUTaal89V2y1sj3qI9/rB66O2K1XsWaTiYFTpWNd7m92ue7lh1qjWet7O9auhU7tWA017NtKnMpl221bJXNvOt5elUxr8XQER3I8v+9V8qWm66C+49dtyjqZJxlXOFK/Vj3KOV3hmCcrO82GG4S9U5Ql5i9FDiLaX0vybXIiO0VuoiW1rcrNw08Hv7+UeOpUwqB3aOpaWcivHnOnjqf7XUb8ooef03cq5cGh55/jGz9f6NS8OtwlvIMQ23D++Q2J5LnPv+ByI+yF+GITuOBYsbO60Il9EdTTnWuRJ7BUQ6Rl1xzzvBUeuF7HdXFNHxzrjATVC1i/CI3nck1wJb4/8YMvYJuIHy0Yi+72P3zy6dt/k7Ie/gM=
diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml
index fdcbe1c0ccc..c972c7f5cfc 100644
--- a/docs/diagrams/tracing/LogicSequenceDiagram.puml
+++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml
@@ -13,7 +13,7 @@ create ecp
abp -> ecp
abp -> ecp ++: parse(arguments)
create ec
-ecp -> ec ++: index, editPersonDescriptor
+ecp -> ec ++: index, editTaskDescriptor
ec --> ecp --
ecp --> abp --: command
abp --> logic --: command
diff --git a/docs/images/AddReminderSequenceDiagram.png b/docs/images/AddReminderSequenceDiagram.png
new file mode 100644
index 00000000000..36da5de08df
Binary files /dev/null and b/docs/images/AddReminderSequenceDiagram.png differ
diff --git a/docs/images/ArchitectureDiagram.png b/docs/images/ArchitectureDiagram.png
index aa2d337d932..40876fb076b 100644
Binary files a/docs/images/ArchitectureDiagram.png and b/docs/images/ArchitectureDiagram.png differ
diff --git a/docs/images/ArchitectureDiagram2.png b/docs/images/ArchitectureDiagram2.png
new file mode 100644
index 00000000000..0e3c4ebc2fc
Binary files /dev/null and b/docs/images/ArchitectureDiagram2.png differ
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
index aa198138f8f..9c26eb7857d 100644
Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ
diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/BetterModelClassDiagram.png
deleted file mode 100644
index bc7ed18ae29..00000000000
Binary files a/docs/images/BetterModelClassDiagram.png and /dev/null differ
diff --git a/docs/images/CalendarCommandActivityDiagram.png b/docs/images/CalendarCommandActivityDiagram.png
new file mode 100644
index 00000000000..d7c8847d381
Binary files /dev/null and b/docs/images/CalendarCommandActivityDiagram.png differ
diff --git a/docs/images/CalendarDayCards.png b/docs/images/CalendarDayCards.png
new file mode 100644
index 00000000000..cfc377f941d
Binary files /dev/null and b/docs/images/CalendarDayCards.png differ
diff --git a/docs/images/CalendarUiClassDiagram.png b/docs/images/CalendarUiClassDiagram.png
new file mode 100644
index 00000000000..b55e8cf54d1
Binary files /dev/null and b/docs/images/CalendarUiClassDiagram.png differ
diff --git a/docs/images/CalendarViewSequenceDiagram.png b/docs/images/CalendarViewSequenceDiagram.png
new file mode 100644
index 00000000000..df17649bea9
Binary files /dev/null and b/docs/images/CalendarViewSequenceDiagram.png differ
diff --git a/docs/images/CommitActivityDiagram.png b/docs/images/CommitActivityDiagram.png
index 4de4fa4bf2b..3fa7ec3f24f 100644
Binary files a/docs/images/CommitActivityDiagram.png and b/docs/images/CommitActivityDiagram.png differ
diff --git a/docs/images/DeleteReminderSequenceDiagram.png b/docs/images/DeleteReminderSequenceDiagram.png
new file mode 100644
index 00000000000..8541dead920
Binary files /dev/null and b/docs/images/DeleteReminderSequenceDiagram.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
index fa327b39618..d8a06b55e70 100644
Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ
diff --git a/docs/images/ExpectedUi.png b/docs/images/ExpectedUi.png
new file mode 100644
index 00000000000..d69a5a7674f
Binary files /dev/null and b/docs/images/ExpectedUi.png differ
diff --git a/docs/images/ListCommandActivityDiagram.png b/docs/images/ListCommandActivityDiagram.png
new file mode 100644
index 00000000000..39df98182b4
Binary files /dev/null and b/docs/images/ListCommandActivityDiagram.png differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
index b9e853cef12..cdd5a0dab28 100644
Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index 280064118cf..68fceb2be27 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/ModelMoreOOP.png b/docs/images/ModelMoreOOP.png
new file mode 100644
index 00000000000..2a2c970e0ce
Binary files /dev/null and b/docs/images/ModelMoreOOP.png differ
diff --git a/docs/images/PriorityMarkupForTaskCards.png b/docs/images/PriorityMarkupForTaskCards.png
new file mode 100644
index 00000000000..4771adec183
Binary files /dev/null and b/docs/images/PriorityMarkupForTaskCards.png differ
diff --git a/docs/images/ProductivityClassDiagram.png b/docs/images/ProductivityClassDiagram.png
new file mode 100644
index 00000000000..9aa2e2124a6
Binary files /dev/null and b/docs/images/ProductivityClassDiagram.png differ
diff --git a/docs/images/Reminderclass.png b/docs/images/Reminderclass.png
new file mode 100644
index 00000000000..bdc72c120d2
Binary files /dev/null and b/docs/images/Reminderclass.png differ
diff --git a/docs/images/StartActivityDiagram.png b/docs/images/StartActivityDiagram.png
new file mode 100644
index 00000000000..12cbf396abb
Binary files /dev/null and b/docs/images/StartActivityDiagram.png differ
diff --git a/docs/images/StopSequenceDiagram.png b/docs/images/StopSequenceDiagram.png
new file mode 100644
index 00000000000..63f59ba99e6
Binary files /dev/null and b/docs/images/StopSequenceDiagram.png differ
diff --git a/docs/images/Storage.png b/docs/images/Storage.png
new file mode 100644
index 00000000000..155e7691f7f
Binary files /dev/null and b/docs/images/Storage.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png
deleted file mode 100644
index d87c1216820..00000000000
Binary files a/docs/images/StorageClassDiagram.png and /dev/null differ
diff --git a/docs/images/SummaryCommandSequenceDiagram.png b/docs/images/SummaryCommandSequenceDiagram.png
new file mode 100644
index 00000000000..856bbc4aeb3
Binary files /dev/null and b/docs/images/SummaryCommandSequenceDiagram.png differ
diff --git a/docs/images/SummaryPanelClassDiagram.png b/docs/images/SummaryPanelClassDiagram.png
new file mode 100644
index 00000000000..2c930163e6e
Binary files /dev/null and b/docs/images/SummaryPanelClassDiagram.png differ
diff --git a/docs/images/SummarySwitchTabSequenceDiagram.png b/docs/images/SummarySwitchTabSequenceDiagram.png
new file mode 100644
index 00000000000..1c86c1c1cd5
Binary files /dev/null and b/docs/images/SummarySwitchTabSequenceDiagram.png differ
diff --git a/docs/images/TabPresentationFormat.png b/docs/images/TabPresentationFormat.png
new file mode 100644
index 00000000000..debb2378525
Binary files /dev/null and b/docs/images/TabPresentationFormat.png differ
diff --git a/docs/images/TaskListClassDiagram.png b/docs/images/TaskListClassDiagram.png
new file mode 100644
index 00000000000..50a3f994201
Binary files /dev/null and b/docs/images/TaskListClassDiagram.png differ
diff --git a/docs/images/TaskListPanelClassDiagram.png b/docs/images/TaskListPanelClassDiagram.png
new file mode 100644
index 00000000000..d0c70d4c8cb
Binary files /dev/null and b/docs/images/TaskListPanelClassDiagram.png differ
diff --git a/docs/images/TaskListTab.png b/docs/images/TaskListTab.png
new file mode 100644
index 00000000000..923b078d985
Binary files /dev/null and b/docs/images/TaskListTab.png differ
diff --git a/docs/images/TimerPanelActivityDiagram.png b/docs/images/TimerPanelActivityDiagram.png
new file mode 100644
index 00000000000..551b643bd31
Binary files /dev/null and b/docs/images/TimerPanelActivityDiagram.png differ
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5bd77847aa2..dcb99c49842 100644
Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ
diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png
index 7b4b3dbea45..6c2709268b5 100644
Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ
diff --git a/docs/images/UndoRedoState0.png b/docs/images/UndoRedoState0.png
index 8f7538cd884..68ed91ab76e 100644
Binary files a/docs/images/UndoRedoState0.png and b/docs/images/UndoRedoState0.png differ
diff --git a/docs/images/UndoRedoState1.png b/docs/images/UndoRedoState1.png
index df9908d0948..a96f4b5510d 100644
Binary files a/docs/images/UndoRedoState1.png and b/docs/images/UndoRedoState1.png differ
diff --git a/docs/images/UndoRedoState2.png b/docs/images/UndoRedoState2.png
index 36519c1015b..b9cf25e7e09 100644
Binary files a/docs/images/UndoRedoState2.png and b/docs/images/UndoRedoState2.png differ
diff --git a/docs/images/UndoRedoState3.png b/docs/images/UndoRedoState3.png
index 19959d01712..c83b65f5d77 100644
Binary files a/docs/images/UndoRedoState3.png and b/docs/images/UndoRedoState3.png differ
diff --git a/docs/images/UndoRedoState4.png b/docs/images/UndoRedoState4.png
index 4c623e4f2c5..939a26d01f4 100644
Binary files a/docs/images/UndoRedoState4.png and b/docs/images/UndoRedoState4.png differ
diff --git a/docs/images/UndoRedoState5.png b/docs/images/UndoRedoState5.png
index 84ad2afa6bd..d153e57ced3 100644
Binary files a/docs/images/UndoRedoState5.png and b/docs/images/UndoRedoState5.png differ
diff --git a/docs/images/UndoSequenceDiagram.png b/docs/images/UndoSequenceDiagram.png
index 6addcd3a8d9..a376e60e449 100644
Binary files a/docs/images/UndoSequenceDiagram.png and b/docs/images/UndoSequenceDiagram.png differ
diff --git a/docs/images/UseCaseDiagram.png b/docs/images/UseCaseDiagram.png
new file mode 100644
index 00000000000..3128f91ba6c
Binary files /dev/null and b/docs/images/UseCaseDiagram.png differ
diff --git a/docs/images/ViewTaskListGetSequenceDiagram.png b/docs/images/ViewTaskListGetSequenceDiagram.png
new file mode 100644
index 00000000000..607c28a9904
Binary files /dev/null and b/docs/images/ViewTaskListGetSequenceDiagram.png differ
diff --git a/docs/images/add-remark/ParserInterface.png b/docs/images/add-remark/ParserInterface.png
index c02c9f7c0cb..f1c91a5226f 100644
Binary files a/docs/images/add-remark/ParserInterface.png and b/docs/images/add-remark/ParserInterface.png differ
diff --git a/docs/images/addReminder.png b/docs/images/addReminder.png
new file mode 100644
index 00000000000..e0f3eecc951
Binary files /dev/null and b/docs/images/addReminder.png differ
diff --git a/docs/images/addReminderReferenceDiagram.png b/docs/images/addReminderReferenceDiagram.png
new file mode 100644
index 00000000000..bb1154ad206
Binary files /dev/null and b/docs/images/addReminderReferenceDiagram.png differ
diff --git a/docs/images/alam8064.png b/docs/images/alam8064.png
new file mode 100644
index 00000000000..1bb13f65582
Binary files /dev/null and b/docs/images/alam8064.png differ
diff --git a/docs/images/clouddoggo.png b/docs/images/clouddoggo.png
new file mode 100644
index 00000000000..1f385f3dcd9
Binary files /dev/null and b/docs/images/clouddoggo.png differ
diff --git a/docs/images/damithc.jpg b/docs/images/damithc.jpg
deleted file mode 100644
index 12754388389..00000000000
Binary files a/docs/images/damithc.jpg and /dev/null differ
diff --git a/docs/images/eedenong.png b/docs/images/eedenong.png
new file mode 100644
index 00000000000..23408e47130
Binary files /dev/null and b/docs/images/eedenong.png differ
diff --git a/docs/images/getCommandResultReferenceDiagram.png b/docs/images/getCommandResultReferenceDiagram.png
new file mode 100644
index 00000000000..e9567432f6f
Binary files /dev/null and b/docs/images/getCommandResultReferenceDiagram.png differ
diff --git a/docs/images/icons/Important.png b/docs/images/icons/Important.png
new file mode 100644
index 00000000000..01ad8c2302c
Binary files /dev/null and b/docs/images/icons/Important.png differ
diff --git a/docs/images/icons/bulb.png b/docs/images/icons/bulb.png
new file mode 100644
index 00000000000..84fe4ff402f
Binary files /dev/null and b/docs/images/icons/bulb.png differ
diff --git a/docs/images/icons/note.png b/docs/images/icons/note.png
new file mode 100644
index 00000000000..6d61cbe31fb
Binary files /dev/null and b/docs/images/icons/note.png differ
diff --git a/docs/images/interaction.png b/docs/images/interaction.png
new file mode 100644
index 00000000000..950bf9cc6e6
Binary files /dev/null and b/docs/images/interaction.png differ
diff --git a/docs/images/lejolly.jpg b/docs/images/lejolly.jpg
deleted file mode 100644
index 2d1d94e0cf5..00000000000
Binary files a/docs/images/lejolly.jpg and /dev/null differ
diff --git a/docs/images/m133225.jpg b/docs/images/m133225.jpg
deleted file mode 100644
index fd14fb94593..00000000000
Binary files a/docs/images/m133225.jpg and /dev/null differ
diff --git a/docs/images/saveJelphaBot.png b/docs/images/saveJelphaBot.png
new file mode 100644
index 00000000000..2598036a0ae
Binary files /dev/null and b/docs/images/saveJelphaBot.png differ
diff --git a/docs/images/ug_figures/.png b/docs/images/ug_figures/.png
new file mode 100644
index 00000000000..c9acbb6d842
Binary files /dev/null and b/docs/images/ug_figures/.png differ
diff --git a/docs/images/ug_figures/CalendarDate.png b/docs/images/ug_figures/CalendarDate.png
new file mode 100644
index 00000000000..90aeb29d59d
Binary files /dev/null and b/docs/images/ug_figures/CalendarDate.png differ
diff --git a/docs/images/ug_figures/CalendarTab.png b/docs/images/ug_figures/CalendarTab.png
new file mode 100644
index 00000000000..9c758b39865
Binary files /dev/null and b/docs/images/ug_figures/CalendarTab.png differ
diff --git a/docs/images/ug_figures/CalendarToday.png b/docs/images/ug_figures/CalendarToday.png
new file mode 100644
index 00000000000..af392649731
Binary files /dev/null and b/docs/images/ug_figures/CalendarToday.png differ
diff --git a/docs/images/ug_figures/CalendarUi.png b/docs/images/ug_figures/CalendarUi.png
new file mode 100644
index 00000000000..3990224abf7
Binary files /dev/null and b/docs/images/ug_figures/CalendarUi.png differ
diff --git a/docs/images/ug_figures/CalendarView.png b/docs/images/ug_figures/CalendarView.png
new file mode 100644
index 00000000000..f61388d282f
Binary files /dev/null and b/docs/images/ug_figures/CalendarView.png differ
diff --git a/docs/images/ug_figures/ProductivityTab.png b/docs/images/ug_figures/ProductivityTab.png
new file mode 100644
index 00000000000..cc1464f72d1
Binary files /dev/null and b/docs/images/ug_figures/ProductivityTab.png differ
diff --git a/docs/images/ug_figures/SummaryViewAfterTaskComplete.png b/docs/images/ug_figures/SummaryViewAfterTaskComplete.png
new file mode 100644
index 00000000000..21f006cc2b4
Binary files /dev/null and b/docs/images/ug_figures/SummaryViewAfterTaskComplete.png differ
diff --git a/docs/images/ug_figures/TaskListTab.png b/docs/images/ug_figures/TaskListTab.png
new file mode 100644
index 00000000000..dcedc6dce66
Binary files /dev/null and b/docs/images/ug_figures/TaskListTab.png differ
diff --git a/docs/images/ug_figures/Ui.png b/docs/images/ug_figures/Ui.png
new file mode 100644
index 00000000000..dcb99c49842
Binary files /dev/null and b/docs/images/ug_figures/Ui.png differ
diff --git a/docs/images/ug_figures/UiAnnotated.png b/docs/images/ug_figures/UiAnnotated.png
new file mode 100644
index 00000000000..8be65064579
Binary files /dev/null and b/docs/images/ug_figures/UiAnnotated.png differ
diff --git a/docs/images/ug_figures/addCommand.png b/docs/images/ug_figures/addCommand.png
new file mode 100644
index 00000000000..8fa96c06749
Binary files /dev/null and b/docs/images/ug_figures/addCommand.png differ
diff --git a/docs/images/ug_figures/addReminder.png b/docs/images/ug_figures/addReminder.png
new file mode 100644
index 00000000000..78617a7b688
Binary files /dev/null and b/docs/images/ug_figures/addReminder.png differ
diff --git a/docs/images/ug_figures/addReminderTab.png b/docs/images/ug_figures/addReminderTab.png
new file mode 100644
index 00000000000..7a355bd4b2f
Binary files /dev/null and b/docs/images/ug_figures/addReminderTab.png differ
diff --git a/docs/images/ug_figures/clearCommand.png b/docs/images/ug_figures/clearCommand.png
new file mode 100644
index 00000000000..35008f4e476
Binary files /dev/null and b/docs/images/ug_figures/clearCommand.png differ
diff --git a/docs/images/ug_figures/delReminder.png b/docs/images/ug_figures/delReminder.png
new file mode 100644
index 00000000000..a39bc26d6bb
Binary files /dev/null and b/docs/images/ug_figures/delReminder.png differ
diff --git a/docs/images/ug_figures/delReminderTab.png b/docs/images/ug_figures/delReminderTab.png
new file mode 100644
index 00000000000..1bf8cbfe330
Binary files /dev/null and b/docs/images/ug_figures/delReminderTab.png differ
diff --git a/docs/images/ug_figures/deleteCommand.png b/docs/images/ug_figures/deleteCommand.png
new file mode 100644
index 00000000000..23a94e43d2f
Binary files /dev/null and b/docs/images/ug_figures/deleteCommand.png differ
diff --git a/docs/images/ug_figures/doneCommand.png b/docs/images/ug_figures/doneCommand.png
new file mode 100644
index 00000000000..3a08134d161
Binary files /dev/null and b/docs/images/ug_figures/doneCommand.png differ
diff --git a/docs/images/ug_figures/editCommand.png b/docs/images/ug_figures/editCommand.png
new file mode 100644
index 00000000000..3c99249c636
Binary files /dev/null and b/docs/images/ug_figures/editCommand.png differ
diff --git a/docs/images/ug_figures/findCommand.png b/docs/images/ug_figures/findCommand.png
new file mode 100644
index 00000000000..21b406bff39
Binary files /dev/null and b/docs/images/ug_figures/findCommand.png differ
diff --git a/docs/images/ug_figures/help.png b/docs/images/ug_figures/help.png
new file mode 100644
index 00000000000..8b73084efb6
Binary files /dev/null and b/docs/images/ug_figures/help.png differ
diff --git a/docs/images/ug_figures/listByDate.png b/docs/images/ug_figures/listByDate.png
new file mode 100644
index 00000000000..5667c126041
Binary files /dev/null and b/docs/images/ug_figures/listByDate.png differ
diff --git a/docs/images/ug_figures/listByModule.png b/docs/images/ug_figures/listByModule.png
new file mode 100644
index 00000000000..71614547dc6
Binary files /dev/null and b/docs/images/ug_figures/listByModule.png differ
diff --git a/docs/images/ug_figures/reminderpopup.png b/docs/images/ug_figures/reminderpopup.png
new file mode 100644
index 00000000000..0180764e22d
Binary files /dev/null and b/docs/images/ug_figures/reminderpopup.png differ
diff --git a/docs/images/ug_figures/remindertab.png b/docs/images/ug_figures/remindertab.png
new file mode 100644
index 00000000000..74ecf5eafb0
Binary files /dev/null and b/docs/images/ug_figures/remindertab.png differ
diff --git a/docs/images/ug_figures/showCompletedCommand.png b/docs/images/ug_figures/showCompletedCommand.png
new file mode 100644
index 00000000000..3e26afefa2e
Binary files /dev/null and b/docs/images/ug_figures/showCompletedCommand.png differ
diff --git a/docs/images/ug_figures/showCompletedCommandNoCompleted.png b/docs/images/ug_figures/showCompletedCommandNoCompleted.png
new file mode 100644
index 00000000000..9fde1d58148
Binary files /dev/null and b/docs/images/ug_figures/showCompletedCommandNoCompleted.png differ
diff --git a/docs/images/ug_figures/showIncompleteCommand.png b/docs/images/ug_figures/showIncompleteCommand.png
new file mode 100644
index 00000000000..761b1bdcd52
Binary files /dev/null and b/docs/images/ug_figures/showIncompleteCommand.png differ
diff --git a/docs/images/ug_figures/showIncompleteCommandNoIncomplete.png b/docs/images/ug_figures/showIncompleteCommandNoIncomplete.png
new file mode 100644
index 00000000000..b8756c898e3
Binary files /dev/null and b/docs/images/ug_figures/showIncompleteCommandNoIncomplete.png differ
diff --git a/docs/images/ug_figures/startCommand.png b/docs/images/ug_figures/startCommand.png
new file mode 100644
index 00000000000..c88ddde7fe5
Binary files /dev/null and b/docs/images/ug_figures/startCommand.png differ
diff --git a/docs/images/ug_figures/stopCommand.png b/docs/images/ug_figures/stopCommand.png
new file mode 100644
index 00000000000..ad3dcda68b1
Binary files /dev/null and b/docs/images/ug_figures/stopCommand.png differ
diff --git a/docs/images/ug_figures/summaryTab.png b/docs/images/ug_figures/summaryTab.png
new file mode 100644
index 00000000000..e19a99cf56e
Binary files /dev/null and b/docs/images/ug_figures/summaryTab.png differ
diff --git a/docs/images/yaojiethng.png b/docs/images/yaojiethng.png
new file mode 100644
index 00000000000..c63f40ffa0c
Binary files /dev/null and b/docs/images/yaojiethng.png differ
diff --git a/docs/images/yapdianhao.png b/docs/images/yapdianhao.png
new file mode 100644
index 00000000000..6e69b89a184
Binary files /dev/null and b/docs/images/yapdianhao.png differ
diff --git a/docs/images/yijinl.jpg b/docs/images/yijinl.jpg
deleted file mode 100644
index adbf62ad940..00000000000
Binary files a/docs/images/yijinl.jpg and /dev/null differ
diff --git a/docs/images/yl_coder.jpg b/docs/images/yl_coder.jpg
deleted file mode 100644
index 17b48a73227..00000000000
Binary files a/docs/images/yl_coder.jpg and /dev/null differ
diff --git a/docs/stylesheets/asciidoctor.css b/docs/stylesheets/asciidoctor.css
index 36590bf346c..5364a5888a8 100644
--- a/docs/stylesheets/asciidoctor.css
+++ b/docs/stylesheets/asciidoctor.css
@@ -295,7 +295,7 @@ td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
-.imageblock>.title{margin-bottom:0}
+.imageblock>.title{margin-bottom:0; text-align: inherit;}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
diff --git a/docs/stylesheets/gh-pages.css b/docs/stylesheets/gh-pages.css
index 121cac3885f..33980b7793e 100644
--- a/docs/stylesheets/gh-pages.css
+++ b/docs/stylesheets/gh-pages.css
@@ -107,7 +107,7 @@ table.tableblock > .title,
justify-content: center;
font-family: "Open Sans", "DejaVu Sans", sans-serif;
font-size: 1rem;
- padding: 0px 1rem;
+ padding: 0 1rem;
}
.navbar-lg {
@@ -164,14 +164,14 @@ table.tableblock > .title,
.navbar-brand {
display: inline-block;
margin-right: 1rem;
- padding: 0.8125rem 0rem;
+ padding: 0.8125rem 0;
padding-left: 0.9375rem;
font-size: 1.25rem;
}
.navbar-brand img {
height: 1.4rem;
- margin: 0rem 0.4rem;
+ margin: 0 0.4rem;
padding: 0;
vertical-align: middle;
}
@@ -189,16 +189,16 @@ table.tableblock > .title,
flex-wrap: wrap;
flex-grow: 1;
align-items: center;
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
list-style: none;
line-height: inherit;
}
.nav-link {
display: block;
- margin: 0px;
- border: 0px;
+ margin: 0;
+ border: 0;
padding: 1rem 1rem;
}
diff --git a/docs/team/alam8064.adoc b/docs/team/alam8064.adoc
new file mode 100644
index 00000000000..fdbc4aac757
--- /dev/null
+++ b/docs/team/alam8064.adoc
@@ -0,0 +1,98 @@
+= Amanda Lam - Project Portfolio
+:site-section: AboutUs
+:imagesDir: ../images
+:stylesDir: ../stylesheets
+
+== PROJECT: JelphaBot
+
+'''
+
+== Overview
+
+JelphaBot is a desktop application integrated with various features for managing tasks efficiently, mainly focusing on
+NUS students as our target group. It is specially designed by my talented crew of teammates, together with myself.
+
+JelphaBot was developed for our software engineering module, CS2103T, where we were tasked to morph an address book
+application that manages contact details into something else. As part of the project constraints, user interactions are
+primarily Command-Line Interface (CLI), assisted with a GUI created using JavaFX.
+It is written in Java, and has about 13 kLoC.
+
+== Summary of contributions
+
+This section contains a summary of my coding, documentation, and other helpful contributions to my team project.
+
+* *Major enhancement*: Implemented the Calendar feature
+** What it does: A calendar integrated to display a monthly calendar of overarching tasks due,
+together with a task list panel on the left for detailed tasks to be shown.
+*** Allow users to navigate to other months of their choice.
+*** Allow users to view specific tasks due to be listed on selected dates.
+*** Allow users to navigate directly to today's date of the calendar view, as well as listing out the tasks due today.
+
+** Justification:
+*** The use of a calendar to display a visual view of these information is neat and easy to navigate, making the feature
+more user-friendly.
+*** Integrating a calendar allows users to be able to plan their schedules easily by being able to immediately
+visualise which days are busier with more tasks on hand.
+
+** Highlights:
+*** The overarching view of the tasks displayed on the calendar (shown by the dot indicators) is done by filtering the
+existing main task list.
+*** The implementation was challenging as it required constant updates to be accounted for after other commands
+edits the main task list is input.
+*** Moreover, to avoid user mistakes and increase the feature's usability, the included commands implementation in
+carrying out various functions as listed above uses the same command keyword : `calendar`. This involved the heavy use
+and interaction between the `Ui`, `Logic`, and `Model` components.
+
+** Relevant pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/314[#314],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/299[#299],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/297[#297],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/177[#177],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/174[#174],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/165[#165],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/138[#138],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/84[#84]
+
+* *Minor enhancement*: Added in the panel of tabs in the main Ui layout during initial stages.
+This was done for the subsequence integration of our individual features.
+** Pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/78[#78]
+
+* *Code contributed*: [https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=alam8064[View on RepoSense]]
+
+* *Other contributions*:
+
+** Project management:
+*** Managed releases `v1.2.1` - `v1.3` (2 releases) on GitHub
+*** Updated `SampleDataUtil` to propagate an empty instance of the app with time-sensitive test data to streamline manual testing.
+(Pull requests: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/357[#357])
+*** Added the screenshots of the figures in the User Guide
+(Pull requests: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/398[#398])
+
+** Documentation:
+*** Added diagrams and documentation for the Calendar feature in the Developer Guide.
+*** Updated diagram for the Ui section, the delete command diagram and the proposed undo feature from AB3 in the Developer Guide.
+*** Added documentation for Calendar feature in the User Guide.
+
+** Community:
+*** Reported bugs and suggestions for other teams:
+https://github.com/alam8064/ped/issues[Reported 11 bugs during PE Dry Run]
+
+== Contributions to the User Guide
+
+|===
+|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.
+The full User Guide can be found https://ay1920s2-cs2103t-f09-2.github.io/main/UserGuide.html[here]._
+|===
+
+include::../UserGuide.adoc[tag=calendar]
+
+== Contributions to the Developer Guide
+
+|===
+|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.
+The full Developer Guide can be found https://ay1920s2-cs2103t-f09-2.github.io/main/DeveloperGuide.html[here]._
+|===
+
+include::../DeveloperGuide.adoc[tag=calendar]
+
diff --git a/docs/team/clouddoggo.adoc b/docs/team/clouddoggo.adoc
new file mode 100644
index 00000000000..a0e43e6a9ef
--- /dev/null
+++ b/docs/team/clouddoggo.adoc
@@ -0,0 +1,78 @@
+= Jel Lim – Project Portfolio
+:site-section: AboutUs
+:imagesDir: ../images
+:stylesDir: ../stylesheets
+
+== Overview
+JelphaBot is a desktop Task Manager that aids NUS students in tracking tasks efficiently. The user interacts with it using a CLI, but it has a GUI created with JavaFX.
+It is written in Java, and has about 13 kLoC.
+
+=== Summary of contributions
+* Code contributed: [https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=clouddoggo&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false[View on RepoSense]]
+
+* Major enhancement:
+Added the start and stop a timer feature for tasks as well as a viewing panel for the user’s overall productivity for the day.
+
+** What it does: `start ` command allows the user to start a timer for the task specified by the index provided.
+The user may stop this timer with `stop ` command. The productivity panel will show the total time spent on as well as the number of tasks completed that are due today.
+
+** Justification: If the user wants to gauge the amount of time spent on their tasks and how many tasks they have completed or an overview of their productivity in that day, it is easy to view all this information in one tab.
+
+** Highlights: This enhancement works with existing as well as future commands. An in-depth analysis of design alternatives was necessary to decide the layout of the productivity panel and how effective it was in improving overall user experience.
+The implementation was also challenging as it was difficult to decide how much data to present to users.
+
+** Credits: Stop and Start command classes were adapted from existing commands such as Edit command.
+
+* Minor enhancement:
+Added a command history that allows the user to navigate to previous commands using up/down keys.
+
+=== Other contributions:
+
+* Issues management:
+** Out of a total of 95 issues from versions 1.0 to 1.4. I managed 42 of them on GitHub (examples: https://github.com/AY1920S2-CS2103T-F09-2/main/issues/163[#163] https://github.com/AY1920S2-CS2103T-F09-2/main/issues/263[#263]).
+
+* User stories management:
+** There was a total of 30 user stories, for versions 1.0 to 1.4. I managed 10 of them.
+
+* Documentation:
+** Developer Guide:
+*** Section 3.1, Delete Sequence diagram, whole section of 3.3, 4.1, 4.4, 4.7 +
+*** Appendix C, Use Case diagram, whole section of appendix C8, C9, D, E, F7, F8, F9, F10
+** Language improvements to User Guide : PR https://github.com/AY1920S2-CS2103T-F09-2/main/pull/283[#283], https://github.com/AY1920S2-CS2103T-F09-2/main/pull/300[#300], https://github.com/AY1920S2-CS2103T-F09-2/main/pull/316[#316]
+** Replaced existing UML diagrams to ones that corresponds with our final product: PR https://github.com/AY1920S2-CS2103T-F09-2/main/pull/198[#198], https://github.com/AY1920S2-CS2103T-F09-2/main/pull/326[#326]
+** Added Use Case diagram and Activity diagrams for start command: PR https://github.com/AY1920S2-CS2103T-F09-2/main/pull/326[#326]
+** Added Sequence diagram for stop command: PR https://github.com/AY1920S2-CS2103T-F09-2/main/pull/328[#328]
+
+* Enhancement to existing features:
+** Added DateTime model to Task model to integrate deadlines.
+** Added
+
+* Community:
+** Reviewed Pull Request: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/19[#19]
+** Reported 13 bugs and offered suggestions during PE dry run: https://github.com/Clouddoggo/ped/issues[issues]
+** Reviewed other team's DG: (examples: https://github.com/nus-cs2103-AY1920S2/addressbook-level3/pull/25/files#r398983142[1],
+https://github.com/nus-cs2103-AY1920S2/addressbook-level3/pull/25/files#r398989484[2], https://github.com/nus-cs2103-AY1920S2/addressbook-level3/pull/25/files#r398987630[3])
+
+* Tools:
+** Integrated CI/CD tools (Appveyor and Coveralls) to the team repository.
+
+<<<
+
+== Contributions to User Guide (Extracts)
+
+|===
+|_Below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._
+|===
+
+include::../UserGuide.adoc[tag=productivitytracker]
+
+<<<
+
+== Contributions to Developer Guide (Extracts)
+
+|===
+|_Below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._
+|===
+
+include::../DeveloperGuide.adoc[tag=productivityImplementation]
+include::../DeveloperGuide.adoc[tag=productivityFunctions]
diff --git a/docs/team/eedenong.adoc b/docs/team/eedenong.adoc
new file mode 100644
index 00000000000..10f40bb88db
--- /dev/null
+++ b/docs/team/eedenong.adoc
@@ -0,0 +1,83 @@
+= Ong Eden - Project Portfolio
+:site-section: AboutUs
+:imagesDir: ../images
+:stylesDir: ../stylesheets
+
+== PROJECT: JelphaBot
+
+
+== Overview
+
+JelphaBot is a desktop application that serves as a simple yet comprehensive task manager for NUS students.
+Interactions with the application and commands are entered through CLI. For a better user experience, JavaFX was used to create and enhance the GUI.
+It is writtren in Java, and has about 13 kLoC.
+
+== Summary of contributions
+
+* *Major enhancement*: added *the ability for users to have a summary view of their tasks due and completed within the day*.
+** What it does: allows the user to have a simplified view of all the tasks that are due to be completed within the day, as well as the tasks that the user have completed within the day, under one page. This page is shown upon the startup of the application, and can be accessed anytime
+while using the app by entering the `summary` command.
+** Justification: In the event the user wishes to have a quick look at what tasks he/she has remaining to complete within the day, or to see what tasks he/she has completed
+within the day, the user can easily do so and view this information all under the same page, with just a single command.
+This feature improves the product significantly with the convenience that it provides to the user in obtaining a quick but comprehensive overview of the above-mentioned tasks.
+** Highlights:
+*** This enhancement works with existing commands and commands to be added in future. It required an in-depth analysis of design alternatives so as to determine the optimal layout of the UI of the Summary panel to enhance the user experience as much as possible.
+*** The implementation too was challenging as it required the creation of special predicates to filter the tasks in the user's task list to be displayed, as well as deciding on what information from the tasks to display to the users. Eventually, I decided to display only the Module Code and the Description of the task.
+*** Another challenge during the implementation was ensuring that the tasks that were completed within the day were still displayed when the user exits the application, and starts it again within the same day. This required extra data to be stored and hence required modification of classes in `Storage` to ensure that
+the data was stored correctly.
+** Relevant pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/80[#80],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/172[#172],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/230[#230]
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/243[#243]
+** Credits: The structure and the classes in the summary package (under `Model`) were inspired by that of the productivity package, which is under `Model` as well.
+* *Minor enhancement*: added a `done` command that allows the user to mark a task with the given index as completed.
+** Relevant pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/71[#71]
+
+* *Code contributed*:
+https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=eedenong&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&tabAuthor=eedenong&tabRepo=AY1920S2-CS2103T-F09-2%2Fmain%5Bmaster%5D[Functional Code]
+https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=eedenong&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&tabAuthor=eedenong&tabRepo=AY1920S2-CS2103T-F09-2%2Fmain%5Bmaster%5D[Test Code]
+
+
+== Other contributions:
+
+---
+
+* Issues management:
+** Managed issues on GitHub:
+https://github.com/AY1920S2-CS2103T-F09-2/main/issues/92[#92],
+https://github.com/AY1920S2-CS2103T-F09-2/main/issues/97[#97],
+https://github.com/AY1920S2-CS2103T-F09-2/main/issues/101[#101],
+https://github.com/AY1920S2-CS2103T-F09-2/main/issues/113[#113]
+
+* Enhancements to existing features:
+** Updated and shifted task list filtering logic in relevant Model and Logic classes and APIs so as to not break abstraction between the classes and roles of the classes.
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/170[#170]
+* Documentation:
+** Replaced the Model class diagrams of the User Guide to make them the consistent with the structure of JelphaBot: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/189[#189]
+** Added documentation for SummaryCommand, ShowCompletedCommand and ShowIncompleteCommand in User Guide: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/189[#189]
+** Added documentation and sequence diagrams for SummaryCommand to Developer Guide: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/294[#294], https://github.com/AY1920S2-CS2103T-F09-2/main/pull/336[#336]
+** Added Use Cases UC4 to UC6: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/58[#58]
+* Community:
+** PRs reviewed: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/32[#32]
+** Reviewed other team's application to find and report https://github.com/eedenong/ped/issues[bugs].
+
+== Contributions to the User Guide
+
+|===
+|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._
+|===
+
+include::../UserGuide.adoc[tag=summary]
+
+include::../UserGuide.adoc[tag=showcompleted]
+
+include::../UserGuide.adoc[tag=showincomplete]
+== Contributions to the Developer Guide
+
+|===
+|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._
+|===
+
+include::../DeveloperGuide.adoc[tag=summary]
diff --git a/docs/team/johndoe.adoc b/docs/team/johndoe.adoc
index f39e76e49b2..bf9930383fe 100644
--- a/docs/team/johndoe.adoc
+++ b/docs/team/johndoe.adoc
@@ -5,7 +5,7 @@
== PROJECT: AddressBook - Level 3
----
+'''
== Overview
@@ -52,8 +52,6 @@ _{you can add/remove categories in the list above}_
include::../UserGuide.adoc[tag=delete]
-include::../UserGuide.adoc[tag=dataencryption]
-
== Contributions to the Developer Guide
|===
@@ -62,11 +60,9 @@ include::../UserGuide.adoc[tag=dataencryption]
include::../DeveloperGuide.adoc[tag=undoredo]
-include::../DeveloperGuide.adoc[tag=dataencryption]
-
== PROJECT: PowerPointLabs
----
+'''
_{Optionally, you may include other projects in your portfolio.}_
diff --git a/docs/team/yaojiethng.adoc b/docs/team/yaojiethng.adoc
new file mode 100644
index 00000000000..645a406717f
--- /dev/null
+++ b/docs/team/yaojiethng.adoc
@@ -0,0 +1,103 @@
+= Thng Yao Jie - Project Portfolio
+:site-section: AboutUs
+:imagesDir: ../images
+:stylesDir: ../stylesheets
+
+== PROJECT: JelphaBot
+
+'''
+
+== Overview
+
+JelphaBot is a desktop application to help NUS students manage tasks.
+JelphaBot allows students to track and manage tasks conveniently.
+Users enter commands in JelphaBot through a CLI. However, a GUI is implemented with JavaFX for a smoother user experience.
+It is written in Java, and has about 13 kLoC.
+
+== About this portfolio
+
+This portfolio lists my individual contributions to the JelphaBot.
+It includes a summary of the feature enhancements implemented and contribution to the User Guide and Developer Guide.
+It also details other contributions I made throughout the duration of the project to team-based tasks.
+
+== Summary of contributions
+
+* *Major enhancement*: added the ability for users to *group their tasks by time or module code*, as well as *provided interfaces for other developers to implement new grouping categories*.
+** What it does: allows users to change the way their tasks are listed by switching between a list that shows:
+*** Tasks listed by how soon their due date is to the current date.
+*** Tasks listed by their Module Code.
+** *Justification*: Task management is the core feature of JelphaBot.
+This feature improves the task management process significantly because it allows users to see at first glance their most urgent or important tasks.
+** *Highlights*:
+*** This feature involves full-stack development in `Logic`, `Model`, `Storage` and `Ui` components.
+*** As all other features use `Task` as the underlying Model entity, there was high coupling with features implemented by other groupmates.
+*** This enhancement affected existing commands as `GroupedTaskList` listed showed tasks in a different order from the underlying list stored in the model, and this order would vary depending on the `Category` displayed.
+*** It required model objects to be queried from the displayed index in `Ui` instead of the the default order in `Model` (which was the order in which objects were implemented).
++
+<<<
++
+*** The implementation was challenging as it required changes to be made to existing commands while still reducing conflict with other teammates' work.
+This required many design alternatives to be considered.
+*** All non-User-Interface classes added were backed up with tests.
+** Relevant pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/122[#122],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/161[#161],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/196[#196],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/204[#204],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/205[#205],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/212[#212],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/219[#219],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/228[#228],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/298[#298],
+
+* *Minor enhancement*: Updated the Ui layout for each Task to allow tasks to be distinguished by priority.
+** Pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/196[#196],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/212[#212]
+
+* *Code contributed*: [https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&tabAuthor=yaojiethng&tabRepo=AY1920S2-CS2103T-F09-2%2Fmain%5Bmaster%5D[Functional code]] [https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&tabAuthor=yaojiethng&tabRepo=AY1920S2-CS2103T-F09-2%2Fmain%5Bmaster%5D[Test code]]
+
+* *Other contributions*:
+
+** Project management:
+*** Managed releases `v1.1` - `v1.2` (2 releases) on GitHub.
+*** Refactored `AddressBook 3` to `JelphaBot`
+(Pull requests: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/6[6],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/37[#37],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/24[#24],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/41[#41],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/47[#47])
+** Enhancements to existing features:
+*** Updated the code-base to use Java 8 `LocalDateTime` instead of Java 7 `DateTime`, which fixed some deprecation issues.
+(Pull requests: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/159[#159])
+*** Updated `SampleDataUtil` to propagate an empty instance of the app with time-sensitive test data to streamline manual testing.
+(Pull requests: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/129[#129])
+** Documentation:
+*** Updated Logic section from AB3, added diagrams and documentation for the implementation of Tab Grouping feature in Developer Guide.
+*** Added documentation for Task List panel and List Command in User Guide.
+
+** Tools:
+*** Integrated Github plugins (gh-pages, Travis, Netlify) to the team repository.
+
+<<<
+
+== Contributions to the User Guide
+
+|===
+|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._
+|===
+
+include::../UserGuide.adoc[tag=tasklist]
+
+<<<
+include::../UserGuide.adoc[tag=list]
+
+<<<
+== Contributions to the Developer Guide
+
+|===
+|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._
+|===
+
+include::../DeveloperGuide.adoc[tag=taskgroups]
+
diff --git a/docs/team/yaojiethng.pdf b/docs/team/yaojiethng.pdf
new file mode 100644
index 00000000000..def1fc6d886
Binary files /dev/null and b/docs/team/yaojiethng.pdf differ
diff --git a/docs/team/yapdianhao.adoc b/docs/team/yapdianhao.adoc
new file mode 100644
index 00000000000..154a599c663
--- /dev/null
+++ b/docs/team/yapdianhao.adoc
@@ -0,0 +1,77 @@
+= Yap Dian Hao - Project Portfolio
+:site-section: AboutUs
+:imagesDir: ../images
+:stylesDir: ../stylesheets
+
+== PROJECT: JelphaBot
+
+'''
+
+== Overview
+JelphaBot is a desktop application to help NUS students manage tasks.
+JelphaBot allows students to track and manage tasks conveniently.
+Users enter commands in JelphaBot through a CLI. However, a GUI is implemented with JavaFX for a smoother user experience.
+It is written in Java, and has about 13 kLoC.
+
+== Summary of contributions
+* *Major enhancement*: added *the ability for users to add reminders to certain tasks*.
+** What it does: allows users to add or remove reminders to remind tasks that will due soon to increase users' efficiency, including:
+*** Tasks that are uncompleted
+*** Tasks that will due within a week
+** Justification: As our target users are students with a lot of commitments, students may miss out several
+commitments over time. Therefore, they will need to manage their tasks and schedule upcoming tasks accordingly. Therefore,
+we have decided to include a reminding feature in JelphaBot to address this need. I implemented jelphaBot's ability
+to link tasks and reminders, and combined them to maximize users' efficiency in fulfilling their commitments. This adds
+significant feature to JelphaBot, as a task manager and a task reminder.
+** Highlights:
+*** This feature introduces a new class, `Reminder`, which plays the similar significance to `Task`.
+The `Reminder` class is leveraged on the Object-Oriented paradigm that a `Task` needs to be reminded by a `Reminder`,
+therefore they are closely relatable to each other. To successfully design such a class that transcends a wide
+range of components, a complete understanding and thorough analysis of the whole application is required.
+*** Challenging as it requires real time synchronization and integration between GUI and internal logic components.
+For instance, a user, when deletes a `Task`, should observe the deletion of its corresponding `Reminder` from the UI as well.
+*** This feature is implemented in a way that it undergoes the whole application's main components' development, in front-end
+and back-end. It involves the `Ui`, `Logic`, `Model`, and `Storage`, with over 3k lines of functional and test code.
+
+** Relevant pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/88[#88],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/149[#149],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/167[#167],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/179[#179],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/207[#207],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/309[#309],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/346[#346]
+
+* *Code contributed*: https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=yapdianhao&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false[View on Reposense]
+
+* *Minor enhancement*: Increased code coverage from 58% to 62% through writing new tests and improved existing tests.
+** Relevant pull requests:
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/33[#33],
+https://github.com/AY1920S2-CS2103T-F09-2/main/pull/76[#76]
+
+* *Other contributions*:
+** Enhancement to existing features:
+*** Updated the GUI color scheme: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/222[#222]
+** Documentation:
+*** Updated JelphaBot's architecture diagram for Developer Guide.
+*** Updated the `Storage` component's sequence diagram for Developer Guide.
+*** Added Use Case 7 and 8 for Developer Guide.
+*** Added screenshots and descriptions as visual aids for User Guide.
+** Community:
+*** Contributed to forum discussions: requesting usage for third-party libraries (controlsfx) https://github.com/nus-cs2103-AY1920S2/forum/issues/81[#81]
+*** Reviewed pull requests: https://github.com/AY1920S2-CS2103T-F09-2/main/pull/13[#13], https://github.com/AY1920S2-CS2103T-F09-2/main/pull/17[#17]
+*** Reported bugs and suggestions for another team in PE dry run: https://github.com/yapdianhao/ped/issues[Reported 15 bugs]
+
+== Contributions to the User Guide
+
+|===
+|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._
+|===
+include::../UserGuide.adoc[tag=reminder]
+
+== Contributions to the Developer Guide
+
+|===
+|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._
+|===
+include::../DeveloperGuide.adoc[tag=reminder]
diff --git a/docs/templates/_header.html.slim b/docs/templates/_header.html.slim
index 3c2d5aed43c..bbe3a196876 100644
--- a/docs/templates/_header.html.slim
+++ b/docs/templates/_header.html.slim
@@ -55,15 +55,15 @@
- if attr? :author
span.author#author =(attr :author)
br
- - if attr? :email
- span.email#email =sub_macros(attr :email)
+ - if attr? :moduleCode
+ span.moduleCode#moduleCode =sub_macros(attr :moduleCode)
br
- if (authorcount = (attr :authorcount).to_i) > 1
- (2..authorcount).each do |idx|
span.author id="author#{idx}" =(attr "author_#{idx}")
br
- if attr? "email_#{idx}"
- span.email id="email#{idx}" =sub_macros(attr "email_#{idx}")
+ span.moduleCode id="moduleCode#{idx}" =sub_macros(attr "email_#{idx}")
- if attr? :revnumber
span#revnumber #{((attr 'version-label') || '').downcase} #{attr :revnumber}#{',' if attr? :revdate}
'
diff --git a/docs/tutorials/AddRemark.adoc b/docs/tutorials/AddRemark.adoc
index ea388068303..3eb298b2cc4 100644
--- a/docs/tutorials/AddRemark.adoc
+++ b/docs/tutorials/AddRemark.adoc
@@ -28,7 +28,7 @@ Looking in the `logic.command` package, you will notice that each existing comma
All the commands inherit from the abstract class `Command` which means that they must override `execute()`.
Each `Command` returns an instance of `CommandResult` upon success and `CommandResult#feedbackToUser` is printed to the `ResultDisplay`.
-Let's start by creating a new `RemarkCommand` class in the `src/main/java/seedu/address/logic/command` directory.
+Let's start by creating a new `RemarkCommand` class in the `src/main/java/seedu/jelphabot/logic/command` directory.
For now, let's keep `RemarkCommand` as simple as possible and print some output.
We accomplish that by returning a `CommandResult` with an accompanying message.
@@ -268,10 +268,10 @@ Without getting too deep into `fxml`, let's go on a 5 minute adventure to get so
Simply add
[source, java]
.PersonCard.java
-```
+----
@FXML
private Label remark;
-```
+----
to link:https://github.com/nus-cs2103-AY1920S1/addressbook-level3/commit/2758455583f0101ed918a318fc75679270843a0d#diff-0c6b6abcfac8c205e075294f25e851fe[`seedu.address.ui.PersonCard`].
`@FXML` is an annotation that marks a private or protected field and makes it accessible to FXML.
diff --git a/docs/tutorials/RemovingFields.adoc b/docs/tutorials/RemovingFields.adoc
index 5a50b6965a6..0c544879525 100644
--- a/docs/tutorials/RemovingFields.adoc
+++ b/docs/tutorials/RemovingFields.adoc
@@ -24,7 +24,7 @@ Fortunately, the IntelliJ IDEA provides a robust refactoring tool that can ident
Let's try to use it as much as we can.
=== Assisted refactoring
-The `address` field in `Person` is actually an instance of the `seedu.address.model.person.Address` class.
+The `address` field in `Person` is actually an instance of the `seedu.jelphabot.model.task.Address` class.
Since removing the `Address` class will break the application, we start by identifying ``Address``'s usages.
This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis.
Right-click the `Address` class and select `Refactor` > `Safe Delete` through the menu.
@@ -86,7 +86,7 @@ private Label address;
...
-
+
...
----
@@ -104,14 +104,14 @@ While keeping the `address` field in the json files does not cause the tests to
.invalidPersonAddressBook.json
[source, json]
-```
+----
{
"persons": [ {
"name": "Person with invalid name field: Ha!ns Mu@ster",
"phone": "9482424",
- "email": "hans@example.com",
+ "moduleCode": "hans@example.com",
"address": "4th street"
} ]
}
-```
+----
You can go through each individual `json` file and manually remove the `address` field.
diff --git a/docs/tutorials/TracingCode.adoc b/docs/tutorials/TracingCode.adoc
index 5f0aaba1741..274b0152699 100644
--- a/docs/tutorials/TracingCode.adoc
+++ b/docs/tutorials/TracingCode.adoc
@@ -49,7 +49,7 @@ However, the execution path through a GUI is often somewhat obscure due to vario
used by GUI frameworks, which happens to be the case here too. Therefore, let us put the breakpoint where the UI transfers
control to the Logic component. According to the sequence diagram, the UI component yields control to the Logic component
through a method named `execute`. Searching through the code base for `execute()` yields a promising candidate in
-`seedu.address.ui.CommandBox.CommandExecutor`.
+`seedu.jelphabot.ui.CommandBox.CommandExecutor`.
.Using the `Search for target by name` feature. `Navigate` > `Symbol`.
image::Execute.png[]
@@ -180,7 +180,7 @@ image::LogicSequenceDiagram.png[]
public CommandResult execute(Model model) throws CommandException {
...
Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
+ Person editedPerson = createEditedPerson(personToEdit, editTaskDescriptor);
if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
throw new CommandException(MESSAGE_DUPLICATE_PERSON);
}
diff --git a/git b/git
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
deleted file mode 100644
index 1deb3a1e469..00000000000
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package seedu.address.commons.core;
-
-/**
- * Container for user visible messages.
- */
-public class Messages {
-
- public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
- public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
-
-}
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java
deleted file mode 100644
index 92cd8fa605a..00000000000
--- a/src/main/java/seedu/address/logic/Logic.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package seedu.address.logic;
-
-import java.nio.file.Path;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * API of the Logic component
- */
-public interface Logic {
- /**
- * Executes the command and returns the result.
- * @param commandText The command as entered by the user.
- * @return the result of the command execution.
- * @throws CommandException If an error occurs during command execution.
- * @throws ParseException If an error occurs during parsing.
- */
- CommandResult execute(String commandText) throws CommandException, ParseException;
-
- /**
- * Returns the AddressBook.
- *
- * @see seedu.address.model.Model#getAddressBook()
- */
- ReadOnlyAddressBook getAddressBook();
-
- /** Returns an unmodifiable view of the filtered list of persons */
- ObservableList getFilteredPersonList();
-
- /**
- * Returns the user prefs' address book file path.
- */
- Path getAddressBookFilePath();
-
- /**
- * Returns the user prefs' GUI settings.
- */
- GuiSettings getGuiSettings();
-
- /**
- * Set the user prefs' GUI settings.
- */
- void setGuiSettings(GuiSettings guiSettings);
-}
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java
deleted file mode 100644
index d47ce874b1a..00000000000
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package seedu.address.logic;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.AddressBookParser;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-import seedu.address.storage.Storage;
-
-/**
- * The main LogicManager of the app.
- */
-public class LogicManager implements Logic {
- public static final String FILE_OPS_ERROR_MESSAGE = "Could not save data to file: ";
- private final Logger logger = LogsCenter.getLogger(LogicManager.class);
-
- private final Model model;
- private final Storage storage;
- private final AddressBookParser addressBookParser;
-
- public LogicManager(Model model, Storage storage) {
- this.model = model;
- this.storage = storage;
- addressBookParser = new AddressBookParser();
- }
-
- @Override
- public CommandResult execute(String commandText) throws CommandException, ParseException {
- logger.info("----------------[USER COMMAND][" + commandText + "]");
-
- CommandResult commandResult;
- Command command = addressBookParser.parseCommand(commandText);
- commandResult = command.execute(model);
-
- try {
- storage.saveAddressBook(model.getAddressBook());
- } catch (IOException ioe) {
- throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
- }
-
- return commandResult;
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return model.getAddressBook();
- }
-
- @Override
- public ObservableList getFilteredPersonList() {
- return model.getFilteredPersonList();
- }
-
- @Override
- public Path getAddressBookFilePath() {
- return model.getAddressBookFilePath();
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- return model.getGuiSettings();
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- model.setGuiSettings(guiSettings);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
deleted file mode 100644
index 71656d7c5c8..00000000000
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Adds a person to the address book.
- */
-public class AddCommand extends Command {
-
- public static final String COMMAND_WORD = "add";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
- + "Parameters: "
- + PREFIX_NAME + "NAME "
- + PREFIX_PHONE + "PHONE "
- + PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " "
- + PREFIX_NAME + "John Doe "
- + PREFIX_PHONE + "98765432 "
- + PREFIX_EMAIL + "johnd@example.com "
- + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
- + PREFIX_TAG + "friends "
- + PREFIX_TAG + "owesMoney";
-
- public static final String MESSAGE_SUCCESS = "New person added: %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book";
-
- private final Person toAdd;
-
- /**
- * Creates an AddCommand to add the specified {@code Person}
- */
- public AddCommand(Person person) {
- requireNonNull(person);
- toAdd = person;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
-
- if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddCommand // instanceof handles nulls
- && toAdd.equals(((AddCommand) other).toAdd));
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
deleted file mode 100644
index 9c86b1fa6e4..00000000000
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-
-/**
- * Clears the address book.
- */
-public class ClearCommand extends Command {
-
- public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.setAddressBook(new AddressBook());
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java
deleted file mode 100644
index 92f900b7916..00000000000
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Objects;
-
-/**
- * Represents the result of a command execution.
- */
-public class CommandResult {
-
- private final String feedbackToUser;
-
- /** Help information should be shown to the user. */
- private final boolean showHelp;
-
- /** The application should exit. */
- private final boolean exit;
-
- /**
- * Constructs a {@code CommandResult} with the specified fields.
- */
- public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) {
- this.feedbackToUser = requireNonNull(feedbackToUser);
- this.showHelp = showHelp;
- this.exit = exit;
- }
-
- /**
- * Constructs a {@code CommandResult} with the specified {@code feedbackToUser},
- * and other fields set to their default value.
- */
- public CommandResult(String feedbackToUser) {
- this(feedbackToUser, false, false);
- }
-
- public String getFeedbackToUser() {
- return feedbackToUser;
- }
-
- public boolean isShowHelp() {
- return showHelp;
- }
-
- public boolean isExit() {
- return exit;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof CommandResult)) {
- return false;
- }
-
- CommandResult otherCommandResult = (CommandResult) other;
- return feedbackToUser.equals(otherCommandResult.feedbackToUser)
- && showHelp == otherCommandResult.showHelp
- && exit == otherCommandResult.exit;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(feedbackToUser, showHelp, exit);
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
deleted file mode 100644
index 02fd256acba..00000000000
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Deletes a person identified using it's displayed index from the address book.
- */
-public class DeleteCommand extends Command {
-
- public static final String COMMAND_WORD = "delete";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Deletes the person identified by the index number used in the displayed person list.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
-
- private final Index targetIndex;
-
- public DeleteCommand(Index targetIndex) {
- this.targetIndex = targetIndex;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (targetIndex.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof DeleteCommand // instanceof handles nulls
- && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
deleted file mode 100644
index 7e36114902f..00000000000
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Edits the details of an existing person in the address book.
- */
-public class EditCommand extends Command {
-
- public static final String COMMAND_WORD = "edit";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
- + "by the index number used in the displayed person list. "
- + "Existing values will be overwritten by the input values.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + "[" + PREFIX_NAME + "NAME] "
- + "[" + PREFIX_PHONE + "PHONE] "
- + "[" + PREFIX_EMAIL + "EMAIL] "
- + "[" + PREFIX_ADDRESS + "ADDRESS] "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + PREFIX_PHONE + "91234567 "
- + PREFIX_EMAIL + "johndoe@example.com";
-
- public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s";
- public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book.";
-
- private final Index index;
- private final EditPersonDescriptor editPersonDescriptor;
-
- /**
- * @param index of the person in the filtered person list to edit
- * @param editPersonDescriptor details to edit the person with
- */
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
- requireNonNull(index);
- requireNonNull(editPersonDescriptor);
-
- this.index = index;
- this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
-
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
- }
-
- /**
- * Creates and returns a {@code Person} with the details of {@code personToEdit}
- * edited with {@code editPersonDescriptor}.
- */
- private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) {
- assert personToEdit != null;
-
- Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
- Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone());
- Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
- Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
- Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
-
- return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags);
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditCommand)) {
- return false;
- }
-
- // state check
- EditCommand e = (EditCommand) other;
- return index.equals(e.index)
- && editPersonDescriptor.equals(e.editPersonDescriptor);
- }
-
- /**
- * Stores the details to edit the person with. Each non-empty field value will replace the
- * corresponding field value of the person.
- */
- public static class EditPersonDescriptor {
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- public EditPersonDescriptor() {}
-
- /**
- * Copy constructor.
- * A defensive copy of {@code tags} is used internally.
- */
- public EditPersonDescriptor(EditPersonDescriptor toCopy) {
- setName(toCopy.name);
- setPhone(toCopy.phone);
- setEmail(toCopy.email);
- setAddress(toCopy.address);
- setTags(toCopy.tags);
- }
-
- /**
- * Returns true if at least one field is edited.
- */
- public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
- }
-
- public void setName(Name name) {
- this.name = name;
- }
-
- public Optional getName() {
- return Optional.ofNullable(name);
- }
-
- public void setPhone(Phone phone) {
- this.phone = phone;
- }
-
- public Optional getPhone() {
- return Optional.ofNullable(phone);
- }
-
- public void setEmail(Email email) {
- this.email = email;
- }
-
- public Optional getEmail() {
- return Optional.ofNullable(email);
- }
-
- public void setAddress(Address address) {
- this.address = address;
- }
-
- public Optional getAddress() {
- return Optional.ofNullable(address);
- }
-
- /**
- * Sets {@code tags} to this object's {@code tags}.
- * A defensive copy of {@code tags} is used internally.
- */
- public void setTags(Set tags) {
- this.tags = (tags != null) ? new HashSet<>(tags) : null;
- }
-
- /**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
- */
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditPersonDescriptor)) {
- return false;
- }
-
- // state check
- EditPersonDescriptor e = (EditPersonDescriptor) other;
-
- return getName().equals(e.getName())
- && getPhone().equals(e.getPhone())
- && getEmail().equals(e.getEmail())
- && getAddress().equals(e.getAddress())
- && getTags().equals(e.getTags());
- }
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
deleted file mode 100644
index d6b19b0a0de..00000000000
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case insensitive.
- */
-public class FindCommand extends Command {
-
- public static final String COMMAND_WORD = "find";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
-
- private final NameContainsKeywordsPredicate predicate;
-
- public FindCommand(NameContainsKeywordsPredicate predicate) {
- this.predicate = predicate;
- }
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(predicate);
- return new CommandResult(
- String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof FindCommand // instanceof handles nulls
- && predicate.equals(((FindCommand) other).predicate)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
deleted file mode 100644
index 84be6ad2596..00000000000
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import seedu.address.model.Model;
-
-/**
- * Lists all persons in the address book to the user.
- */
-public class ListCommand extends Command {
-
- public static final String COMMAND_WORD = "list";
-
- public static final String MESSAGE_SUCCESS = "Listed all persons";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
deleted file mode 100644
index 3b8bfa035e8..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new AddCommand object
- */
-public class AddCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the AddCommand
- * and returns an AddCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public AddCommand parse(String args) throws ParseException {
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
- || !argMultimap.getPreamble().isEmpty()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-
- Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
- Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get());
- Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
- Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
- Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
-
- Person person = new Person(name, phone, email, address, tagList);
-
- return new AddCommand(person);
- }
-
- /**
- * Returns true if none of the prefixes contains empty {@code Optional} values in the given
- * {@code ArgumentMultimap}.
- */
- private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
- return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
deleted file mode 100644
index 1e466792b46..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * Parses user input.
- */
-public class AddressBookParser {
-
- /**
- * Used for initial separation of command word and args.
- */
- private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- * @throws ParseException if the user input does not conform the expected format
- */
- public Command parseCommand(String userInput) throws ParseException {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
- }
-
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- switch (commandWord) {
-
- case AddCommand.COMMAND_WORD:
- return new AddCommandParser().parse(arguments);
-
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return new DeleteCommandParser().parse(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return new FindCommandParser().parse(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD:
- return new HelpCommand();
-
- default:
- throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
deleted file mode 100644
index 75b1a9bf119..00000000000
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package seedu.address.logic.parser;
-
-/**
- * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
- */
-public class CliSyntax {
-
- /* Prefix definitions */
- public static final Prefix PREFIX_NAME = new Prefix("n/");
- public static final Prefix PREFIX_PHONE = new Prefix("p/");
- public static final Prefix PREFIX_EMAIL = new Prefix("e/");
- public static final Prefix PREFIX_ADDRESS = new Prefix("a/");
- public static final Prefix PREFIX_TAG = new Prefix("t/");
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
deleted file mode 100644
index 845644b7dea..00000000000
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new EditCommand object
- */
-public class EditCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the EditCommand
- * and returns an EditCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public EditCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- Index index;
-
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
- }
-
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
- editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
- }
- if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
- editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
- }
- if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) {
- editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
- }
- if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) {
- editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()));
- }
- parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
-
- if (!editPersonDescriptor.isAnyFieldEdited()) {
- throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
- }
-
- return new EditCommand(index, editPersonDescriptor);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
- * If {@code tags} contain only one element which is an empty string, it will be parsed into a
- * {@code Set} containing zero tags.
- */
- private Optional> parseTagsForEdit(Collection tags) throws ParseException {
- assert tags != null;
-
- if (tags.isEmpty()) {
- return Optional.empty();
- }
- Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
- return Optional.of(ParserUtil.parseTags(tagSet));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
deleted file mode 100644
index b117acb9c55..00000000000
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods used for parsing strings in the various *Parser classes.
- */
-public class ParserUtil {
-
- public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
-
- /**
- * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
- * trimmed.
- * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
- */
- public static Index parseIndex(String oneBasedIndex) throws ParseException {
- String trimmedIndex = oneBasedIndex.trim();
- if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
- throw new ParseException(MESSAGE_INVALID_INDEX);
- }
- return Index.fromOneBased(Integer.parseInt(trimmedIndex));
- }
-
- /**
- * Parses a {@code String name} into a {@code Name}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code name} is invalid.
- */
- public static Name parseName(String name) throws ParseException {
- requireNonNull(name);
- String trimmedName = name.trim();
- if (!Name.isValidName(trimmedName)) {
- throw new ParseException(Name.MESSAGE_CONSTRAINTS);
- }
- return new Name(trimmedName);
- }
-
- /**
- * Parses a {@code String phone} into a {@code Phone}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code phone} is invalid.
- */
- public static Phone parsePhone(String phone) throws ParseException {
- requireNonNull(phone);
- String trimmedPhone = phone.trim();
- if (!Phone.isValidPhone(trimmedPhone)) {
- throw new ParseException(Phone.MESSAGE_CONSTRAINTS);
- }
- return new Phone(trimmedPhone);
- }
-
- /**
- * Parses a {@code String address} into an {@code Address}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code address} is invalid.
- */
- public static Address parseAddress(String address) throws ParseException {
- requireNonNull(address);
- String trimmedAddress = address.trim();
- if (!Address.isValidAddress(trimmedAddress)) {
- throw new ParseException(Address.MESSAGE_CONSTRAINTS);
- }
- return new Address(trimmedAddress);
- }
-
- /**
- * Parses a {@code String email} into an {@code Email}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code email} is invalid.
- */
- public static Email parseEmail(String email) throws ParseException {
- requireNonNull(email);
- String trimmedEmail = email.trim();
- if (!Email.isValidEmail(trimmedEmail)) {
- throw new ParseException(Email.MESSAGE_CONSTRAINTS);
- }
- return new Email(trimmedEmail);
- }
-
- /**
- * Parses a {@code String tag} into a {@code Tag}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code tag} is invalid.
- */
- public static Tag parseTag(String tag) throws ParseException {
- requireNonNull(tag);
- String trimmedTag = tag.trim();
- if (!Tag.isValidTagName(trimmedTag)) {
- throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(trimmedTag);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set}.
- */
- public static Set parseTags(Collection tags) throws ParseException {
- requireNonNull(tags);
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(parseTag(tagName));
- }
- return tagSet;
- }
-}
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
deleted file mode 100644
index 1a943a0781a..00000000000
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.UniquePersonList;
-
-/**
- * Wraps all data at the address-book level
- * Duplicates are not allowed (by .isSamePerson comparison)
- */
-public class AddressBook implements ReadOnlyAddressBook {
-
- private final UniquePersonList persons;
-
- /*
- * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
- * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
- *
- * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
- * among constructors.
- */
- {
- persons = new UniquePersonList();
- }
-
- public AddressBook() {}
-
- /**
- * Creates an AddressBook using the Persons in the {@code toBeCopied}
- */
- public AddressBook(ReadOnlyAddressBook toBeCopied) {
- this();
- resetData(toBeCopied);
- }
-
- //// list overwrite operations
-
- /**
- * Replaces the contents of the person list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- this.persons.setPersons(persons);
- }
-
- /**
- * Resets the existing data of this {@code AddressBook} with {@code newData}.
- */
- public void resetData(ReadOnlyAddressBook newData) {
- requireNonNull(newData);
-
- setPersons(newData.getPersonList());
- }
-
- //// person-level operations
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return persons.contains(person);
- }
-
- /**
- * Adds a person to the address book.
- * The person must not already exist in the address book.
- */
- public void addPerson(Person p) {
- persons.add(p);
- }
-
- /**
- * Replaces the given person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireNonNull(editedPerson);
-
- persons.setPerson(target, editedPerson);
- }
-
- /**
- * Removes {@code key} from this {@code AddressBook}.
- * {@code key} must exist in the address book.
- */
- public void removePerson(Person key) {
- persons.remove(key);
- }
-
- //// util methods
-
- @Override
- public String toString() {
- return persons.asUnmodifiableObservableList().size() + " persons";
- // TODO: refine later
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons.asUnmodifiableObservableList();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddressBook // instanceof handles nulls
- && persons.equals(((AddressBook) other).persons));
- }
-
- @Override
- public int hashCode() {
- return persons.hashCode();
- }
-}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
deleted file mode 100644
index d54df471c1f..00000000000
--- a/src/main/java/seedu/address/model/Model.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.model;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.Person;
-
-/**
- * The API of the Model component.
- */
-public interface Model {
- /** {@code Predicate} that always evaluate to true */
- Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
-
- /**
- * Replaces user prefs data with the data in {@code userPrefs}.
- */
- void setUserPrefs(ReadOnlyUserPrefs userPrefs);
-
- /**
- * Returns the user prefs.
- */
- ReadOnlyUserPrefs getUserPrefs();
-
- /**
- * Returns the user prefs' GUI settings.
- */
- GuiSettings getGuiSettings();
-
- /**
- * Sets the user prefs' GUI settings.
- */
- void setGuiSettings(GuiSettings guiSettings);
-
- /**
- * Returns the user prefs' address book file path.
- */
- Path getAddressBookFilePath();
-
- /**
- * Sets the user prefs' address book file path.
- */
- void setAddressBookFilePath(Path addressBookFilePath);
-
- /**
- * Replaces address book data with the data in {@code addressBook}.
- */
- void setAddressBook(ReadOnlyAddressBook addressBook);
-
- /** Returns the AddressBook */
- ReadOnlyAddressBook getAddressBook();
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- boolean hasPerson(Person person);
-
- /**
- * Deletes the given person.
- * The person must exist in the address book.
- */
- void deletePerson(Person target);
-
- /**
- * Adds the given person.
- * {@code person} must not already exist in the address book.
- */
- void addPerson(Person person);
-
- /**
- * Replaces the given person {@code target} with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- void setPerson(Person target, Person editedPerson);
-
- /** Returns an unmodifiable view of the filtered person list */
- ObservableList getFilteredPersonList();
-
- /**
- * Updates the filter of the filtered person list to filter by the given {@code predicate}.
- * @throws NullPointerException if {@code predicate} is null.
- */
- void updateFilteredPersonList(Predicate predicate);
-}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
deleted file mode 100644
index 0650c954f5c..00000000000
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.collections.transformation.FilteredList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Represents the in-memory model of the address book data.
- */
-public class ModelManager implements Model {
- private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
-
- private final AddressBook addressBook;
- private final UserPrefs userPrefs;
- private final FilteredList filteredPersons;
-
- /**
- * Initializes a ModelManager with the given addressBook and userPrefs.
- */
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
- super();
- requireAllNonNull(addressBook, userPrefs);
-
- logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
-
- this.addressBook = new AddressBook(addressBook);
- this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
- }
-
- public ModelManager() {
- this(new AddressBook(), new UserPrefs());
- }
-
- //=========== UserPrefs ==================================================================================
-
- @Override
- public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
- requireNonNull(userPrefs);
- this.userPrefs.resetData(userPrefs);
- }
-
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- return userPrefs;
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- return userPrefs.getGuiSettings();
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- requireNonNull(guiSettings);
- userPrefs.setGuiSettings(guiSettings);
- }
-
- @Override
- public Path getAddressBookFilePath() {
- return userPrefs.getAddressBookFilePath();
- }
-
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- userPrefs.setAddressBookFilePath(addressBookFilePath);
- }
-
- //=========== AddressBook ================================================================================
-
- @Override
- public void setAddressBook(ReadOnlyAddressBook addressBook) {
- this.addressBook.resetData(addressBook);
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return addressBook;
- }
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return addressBook.hasPerson(person);
- }
-
- @Override
- public void deletePerson(Person target) {
- addressBook.removePerson(target);
- }
-
- @Override
- public void addPerson(Person person) {
- addressBook.addPerson(person);
- updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- }
-
- @Override
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- addressBook.setPerson(target, editedPerson);
- }
-
- //=========== Filtered Person List Accessors =============================================================
-
- /**
- * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
- * {@code versionedAddressBook}
- */
- @Override
- public ObservableList getFilteredPersonList() {
- return filteredPersons;
- }
-
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- requireNonNull(predicate);
- filteredPersons.setPredicate(predicate);
- }
-
- @Override
- public boolean equals(Object obj) {
- // short circuit if same object
- if (obj == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(obj instanceof ModelManager)) {
- return false;
- }
-
- // state check
- ModelManager other = (ModelManager) obj;
- return addressBook.equals(other.addressBook)
- && userPrefs.equals(other.userPrefs)
- && filteredPersons.equals(other.filteredPersons);
- }
-
-}
diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
deleted file mode 100644
index 6ddc2cd9a29..00000000000
--- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package seedu.address.model;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-
-/**
- * Unmodifiable view of an address book
- */
-public interface ReadOnlyAddressBook {
-
- /**
- * Returns an unmodifiable view of the persons list.
- * This list will not contain any duplicate persons.
- */
- ObservableList getPersonList();
-
-}
diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java
deleted file mode 100644
index 60472ca22a0..00000000000
--- a/src/main/java/seedu/address/model/person/Address.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's address in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)}
- */
-public class Address {
-
- public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank";
-
- /*
- * The first character of the address must not be a whitespace,
- * otherwise " " (a blank string) becomes a valid input.
- */
- public static final String VALIDATION_REGEX = "[^\\s].*";
-
- public final String value;
-
- /**
- * Constructs an {@code Address}.
- *
- * @param address A valid address.
- */
- public Address(String address) {
- requireNonNull(address);
- checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS);
- value = address;
- }
-
- /**
- * Returns true if a given string is a valid email.
- */
- public static boolean isValidAddress(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Address // instanceof handles nulls
- && value.equals(((Address) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java
deleted file mode 100644
index a5bbe0b6a5f..00000000000
--- a/src/main/java/seedu/address/model/person/Email.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's email in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)}
- */
-public class Email {
-
- private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-";
- public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain "
- + "and adhere to the following constraints:\n"
- + "1. The local-part should only contain alphanumeric characters and these special characters, excluding "
- + "the parentheses, (" + SPECIAL_CHARACTERS + ") .\n"
- + "2. This is followed by a '@' and then a domain name. "
- + "The domain name must:\n"
- + " - be at least 2 characters long\n"
- + " - start and end with alphanumeric characters\n"
- + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, if any.";
- // alphanumeric and special characters
- private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]+";
- private static final String DOMAIN_FIRST_CHARACTER_REGEX = "[^\\W_]"; // alphanumeric characters except underscore
- private static final String DOMAIN_MIDDLE_REGEX = "[a-zA-Z0-9.-]*"; // alphanumeric, period and hyphen
- private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]$";
- public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@"
- + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX;
-
- public final String value;
-
- /**
- * Constructs an {@code Email}.
- *
- * @param email A valid email address.
- */
- public Email(String email) {
- requireNonNull(email);
- checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS);
- value = email;
- }
-
- /**
- * Returns if a given string is a valid email.
- */
- public static boolean isValidEmail(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Email // instanceof handles nulls
- && value.equals(((Email) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/person/Name.java
deleted file mode 100644
index 79244d71cf7..00000000000
--- a/src/main/java/seedu/address/model/person/Name.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's name in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidName(String)}
- */
-public class Name {
-
- public static final String MESSAGE_CONSTRAINTS =
- "Names should only contain alphanumeric characters and spaces, and it should not be blank";
-
- /*
- * The first character of the address must not be a whitespace,
- * otherwise " " (a blank string) becomes a valid input.
- */
- public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
-
- public final String fullName;
-
- /**
- * Constructs a {@code Name}.
- *
- * @param name A valid name.
- */
- public Name(String name) {
- requireNonNull(name);
- checkArgument(isValidName(name), MESSAGE_CONSTRAINTS);
- fullName = name;
- }
-
- /**
- * Returns true if a given string is a valid name.
- */
- public static boolean isValidName(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
-
- @Override
- public String toString() {
- return fullName;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Name // instanceof handles nulls
- && fullName.equals(((Name) other).fullName)); // state check
- }
-
- @Override
- public int hashCode() {
- return fullName.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
deleted file mode 100644
index c9b5868427c..00000000000
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package seedu.address.model.person;
-
-import java.util.List;
-import java.util.function.Predicate;
-
-import seedu.address.commons.util.StringUtil;
-
-/**
- * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
- */
-public class NameContainsKeywordsPredicate implements Predicate {
- private final List keywords;
-
- public NameContainsKeywordsPredicate(List keywords) {
- this.keywords = keywords;
- }
-
- @Override
- public boolean test(Person person) {
- return keywords.stream()
- .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls
- && keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
deleted file mode 100644
index 557a7a60cd5..00000000000
--- a/src/main/java/seedu/address/model/person/Person.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package seedu.address.model.person;
-
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-import seedu.address.model.tag.Tag;
-
-/**
- * Represents a Person in the address book.
- * Guarantees: details are present and not null, field values are validated, immutable.
- */
-public class Person {
-
- // Identity fields
- private final Name name;
- private final Phone phone;
- private final Email email;
-
- // Data fields
- private final Address address;
- private final Set tags = new HashSet<>();
-
- /**
- * Every field must be present and not null.
- */
- public Person(Name name, Phone phone, Email email, Address address, Set tags) {
- requireAllNonNull(name, phone, email, address, tags);
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- this.tags.addAll(tags);
- }
-
- public Name getName() {
- return name;
- }
-
- public Phone getPhone() {
- return phone;
- }
-
- public Email getEmail() {
- return email;
- }
-
- public Address getAddress() {
- return address;
- }
-
- /**
- * Returns an immutable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- */
- public Set getTags() {
- return Collections.unmodifiableSet(tags);
- }
-
- /**
- * Returns true if both persons of the same name have at least one other identity field that is the same.
- * This defines a weaker notion of equality between two persons.
- */
- public boolean isSamePerson(Person otherPerson) {
- if (otherPerson == this) {
- return true;
- }
-
- return otherPerson != null
- && otherPerson.getName().equals(getName())
- && (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail()));
- }
-
- /**
- * Returns true if both persons have the same identity and data fields.
- * This defines a stronger notion of equality between two persons.
- */
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- if (!(other instanceof Person)) {
- return false;
- }
-
- Person otherPerson = (Person) other;
- return otherPerson.getName().equals(getName())
- && otherPerson.getPhone().equals(getPhone())
- && otherPerson.getEmail().equals(getEmail())
- && otherPerson.getAddress().equals(getAddress())
- && otherPerson.getTags().equals(getTags());
- }
-
- @Override
- public int hashCode() {
- // use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append(getName())
- .append(" Phone: ")
- .append(getPhone())
- .append(" Email: ")
- .append(getEmail())
- .append(" Address: ")
- .append(getAddress())
- .append(" Tags: ");
- getTags().forEach(builder::append);
- return builder.toString();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java
deleted file mode 100644
index 872c76b382f..00000000000
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's phone number in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)}
- */
-public class Phone {
-
-
- public static final String MESSAGE_CONSTRAINTS =
- "Phone numbers should only contain numbers, and it should be at least 3 digits long";
- public static final String VALIDATION_REGEX = "\\d{3,}";
- public final String value;
-
- /**
- * Constructs a {@code Phone}.
- *
- * @param phone A valid phone number.
- */
- public Phone(String phone) {
- requireNonNull(phone);
- checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS);
- value = phone;
- }
-
- /**
- * Returns true if a given string is a valid phone number.
- */
- public static boolean isValidPhone(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Phone // instanceof handles nulls
- && value.equals(((Phone) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java
deleted file mode 100644
index 0fee4fe57e6..00000000000
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.util.Iterator;
-import java.util.List;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.model.person.exceptions.PersonNotFoundException;
-
-/**
- * A list of persons that enforces uniqueness between its elements and does not allow nulls.
- * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of
- * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is
- * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so
- * as to ensure that the person with exactly the same fields will be removed.
- *
- * Supports a minimal set of list operations.
- *
- * @see Person#isSamePerson(Person)
- */
-public class UniquePersonList implements Iterable {
-
- private final ObservableList internalList = FXCollections.observableArrayList();
- private final ObservableList internalUnmodifiableList =
- FXCollections.unmodifiableObservableList(internalList);
-
- /**
- * Returns true if the list contains an equivalent person as the given argument.
- */
- public boolean contains(Person toCheck) {
- requireNonNull(toCheck);
- return internalList.stream().anyMatch(toCheck::isSamePerson);
- }
-
- /**
- * Adds a person to the list.
- * The person must not already exist in the list.
- */
- public void add(Person toAdd) {
- requireNonNull(toAdd);
- if (contains(toAdd)) {
- throw new DuplicatePersonException();
- }
- internalList.add(toAdd);
- }
-
- /**
- * Replaces the person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the list.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the list.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- int index = internalList.indexOf(target);
- if (index == -1) {
- throw new PersonNotFoundException();
- }
-
- if (!target.isSamePerson(editedPerson) && contains(editedPerson)) {
- throw new DuplicatePersonException();
- }
-
- internalList.set(index, editedPerson);
- }
-
- /**
- * Removes the equivalent person from the list.
- * The person must exist in the list.
- */
- public void remove(Person toRemove) {
- requireNonNull(toRemove);
- if (!internalList.remove(toRemove)) {
- throw new PersonNotFoundException();
- }
- }
-
- public void setPersons(UniquePersonList replacement) {
- requireNonNull(replacement);
- internalList.setAll(replacement.internalList);
- }
-
- /**
- * Replaces the contents of this list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- requireAllNonNull(persons);
- if (!personsAreUnique(persons)) {
- throw new DuplicatePersonException();
- }
-
- internalList.setAll(persons);
- }
-
- /**
- * Returns the backing list as an unmodifiable {@code ObservableList}.
- */
- public ObservableList asUnmodifiableObservableList() {
- return internalUnmodifiableList;
- }
-
- @Override
- public Iterator iterator() {
- return internalList.iterator();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof UniquePersonList // instanceof handles nulls
- && internalList.equals(((UniquePersonList) other).internalList));
- }
-
- @Override
- public int hashCode() {
- return internalList.hashCode();
- }
-
- /**
- * Returns true if {@code persons} contains only unique persons.
- */
- private boolean personsAreUnique(List persons) {
- for (int i = 0; i < persons.size() - 1; i++) {
- for (int j = i + 1; j < persons.size(); j++) {
- if (persons.get(i).isSamePerson(persons.get(j))) {
- return false;
- }
- }
- }
- return true;
- }
-}
diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
deleted file mode 100644
index d7290f59442..00000000000
--- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package seedu.address.model.person.exceptions;
-
-/**
- * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same
- * identity).
- */
-public class DuplicatePersonException extends RuntimeException {
- public DuplicatePersonException() {
- super("Operation would result in duplicate persons");
- }
-}
diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
deleted file mode 100644
index fa764426ca7..00000000000
--- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package seedu.address.model.person.exceptions;
-
-/**
- * Signals that the operation is unable to find the specified person.
- */
-public class PersonNotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java
deleted file mode 100644
index 1806da4facf..00000000000
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.model.util;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods for populating {@code AddressBook} with sample data.
- */
-public class SampleDataUtil {
- public static Person[] getSamplePersons() {
- return new Person[] {
- new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"),
- new Address("Blk 30 Geylang Street 29, #06-40"),
- getTagSet("friends")),
- new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"),
- new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"),
- getTagSet("colleagues", "friends")),
- new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"),
- new Address("Blk 11 Ang Mo Kio Street 74, #11-04"),
- getTagSet("neighbours")),
- new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"),
- new Address("Blk 436 Serangoon Gardens Street 26, #16-43"),
- getTagSet("family")),
- new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"),
- new Address("Blk 47 Tampines Street 20, #17-35"),
- getTagSet("classmates")),
- new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"),
- new Address("Blk 45 Aljunied Street 85, #11-31"),
- getTagSet("colleagues"))
- };
- }
-
- public static ReadOnlyAddressBook getSampleAddressBook() {
- AddressBook sampleAb = new AddressBook();
- for (Person samplePerson : getSamplePersons()) {
- sampleAb.addPerson(samplePerson);
- }
- return sampleAb;
- }
-
- /**
- * Returns a tag set containing the list of strings given.
- */
- public static Set getTagSet(String... strings) {
- return Arrays.stream(strings)
- .map(Tag::new)
- .collect(Collectors.toSet());
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java
deleted file mode 100644
index 4599182b3f9..00000000000
--- a/src/main/java/seedu/address/storage/AddressBookStorage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * Represents a storage for {@link seedu.address.model.AddressBook}.
- */
-public interface AddressBookStorage {
-
- /**
- * Returns the file path of the data file.
- */
- Path getAddressBookFilePath();
-
- /**
- * Returns AddressBook data as a {@link ReadOnlyAddressBook}.
- * Returns {@code Optional.empty()} if storage file is not found.
- * @throws DataConversionException if the data in storage is not in the expected format.
- * @throws IOException if there was any problem when reading from the storage.
- */
- Optional readAddressBook() throws DataConversionException, IOException;
-
- /**
- * @see #getAddressBookFilePath()
- */
- Optional readAddressBook(Path filePath) throws DataConversionException, IOException;
-
- /**
- * Saves the given {@link ReadOnlyAddressBook} to the storage.
- * @param addressBook cannot be null.
- * @throws IOException if there was any problem writing to the file.
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
- /**
- * @see #saveAddressBook(ReadOnlyAddressBook)
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
deleted file mode 100644
index a6321cec2ea..00000000000
--- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Jackson-friendly version of {@link Person}.
- */
-class JsonAdaptedPerson {
-
- public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!";
-
- private final String name;
- private final String phone;
- private final String email;
- private final String address;
- private final List tagged = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonAdaptedPerson} with the given person details.
- */
- @JsonCreator
- public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone,
- @JsonProperty("email") String email, @JsonProperty("address") String address,
- @JsonProperty("tagged") List tagged) {
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- if (tagged != null) {
- this.tagged.addAll(tagged);
- }
- }
-
- /**
- * Converts a given {@code Person} into this class for Jackson use.
- */
- public JsonAdaptedPerson(Person source) {
- name = source.getName().fullName;
- phone = source.getPhone().value;
- email = source.getEmail().value;
- address = source.getAddress().value;
- tagged.addAll(source.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList()));
- }
-
- /**
- * Converts this Jackson-friendly adapted person object into the model's {@code Person} object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted person.
- */
- public Person toModelType() throws IllegalValueException {
- final List personTags = new ArrayList<>();
- for (JsonAdaptedTag tag : tagged) {
- personTags.add(tag.toModelType());
- }
-
- if (name == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()));
- }
- if (!Name.isValidName(name)) {
- throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS);
- }
- final Name modelName = new Name(name);
-
- if (phone == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()));
- }
- if (!Phone.isValidPhone(phone)) {
- throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS);
- }
- final Phone modelPhone = new Phone(phone);
-
- if (email == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()));
- }
- if (!Email.isValidEmail(email)) {
- throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS);
- }
- final Email modelEmail = new Email(email);
-
- if (address == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()));
- }
- if (!Address.isValidAddress(address)) {
- throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS);
- }
- final Address modelAddress = new Address(address);
-
- final Set modelTags = new HashSet<>(personTags);
- return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
deleted file mode 100644
index dfab9daaa0d..00000000000
--- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package seedu.address.storage;
-
-import static java.util.Objects.requireNonNull;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.FileUtil;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * A class to access AddressBook data stored as a json file on the hard disk.
- */
-public class JsonAddressBookStorage implements AddressBookStorage {
-
- private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class);
-
- private Path filePath;
-
- public JsonAddressBookStorage(Path filePath) {
- this.filePath = filePath;
- }
-
- public Path getAddressBookFilePath() {
- return filePath;
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException {
- return readAddressBook(filePath);
- }
-
- /**
- * Similar to {@link #readAddressBook()}.
- *
- * @param filePath location of the data. Cannot be null.
- * @throws DataConversionException if the file is not in the correct format.
- */
- public Optional readAddressBook(Path filePath) throws DataConversionException {
- requireNonNull(filePath);
-
- Optional jsonAddressBook = JsonUtil.readJsonFile(
- filePath, JsonSerializableAddressBook.class);
- if (!jsonAddressBook.isPresent()) {
- return Optional.empty();
- }
-
- try {
- return Optional.of(jsonAddressBook.get().toModelType());
- } catch (IllegalValueException ive) {
- logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
- throw new DataConversionException(ive);
- }
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, filePath);
- }
-
- /**
- * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}.
- *
- * @param filePath location of the data. Cannot be null.
- */
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- requireNonNull(addressBook);
- requireNonNull(filePath);
-
- FileUtil.createIfMissing(filePath);
- JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
deleted file mode 100644
index 5efd834091d..00000000000
--- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonRootName;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * An Immutable AddressBook that is serializable to JSON format.
- */
-@JsonRootName(value = "addressbook")
-class JsonSerializableAddressBook {
-
- public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s).";
-
- private final List persons = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonSerializableAddressBook} with the given persons.
- */
- @JsonCreator
- public JsonSerializableAddressBook(@JsonProperty("persons") List persons) {
- this.persons.addAll(persons);
- }
-
- /**
- * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use.
- *
- * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}.
- */
- public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList()));
- }
-
- /**
- * Converts this address book into the model's {@code AddressBook} object.
- *
- * @throws IllegalValueException if there were any data constraints violated.
- */
- public AddressBook toModelType() throws IllegalValueException {
- AddressBook addressBook = new AddressBook();
- for (JsonAdaptedPerson jsonAdaptedPerson : persons) {
- Person person = jsonAdaptedPerson.toModelType();
- if (addressBook.hasPerson(person)) {
- throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON);
- }
- addressBook.addPerson(person);
- }
- return addressBook;
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java
deleted file mode 100644
index beda8bd9f11..00000000000
--- a/src/main/java/seedu/address/storage/Storage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * API of the Storage component
- */
-public interface Storage extends AddressBookStorage, UserPrefsStorage {
-
- @Override
- Optional readUserPrefs() throws DataConversionException, IOException;
-
- @Override
- void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
-
- @Override
- Path getAddressBookFilePath();
-
- @Override
- Optional readAddressBook() throws DataConversionException, IOException;
-
- @Override
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java
deleted file mode 100644
index e4f452b6cbf..00000000000
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * Manages storage of AddressBook data in local storage.
- */
-public class StorageManager implements Storage {
-
- private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
- private AddressBookStorage addressBookStorage;
- private UserPrefsStorage userPrefsStorage;
-
-
- public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
- super();
- this.addressBookStorage = addressBookStorage;
- this.userPrefsStorage = userPrefsStorage;
- }
-
- // ================ UserPrefs methods ==============================
-
- @Override
- public Path getUserPrefsFilePath() {
- return userPrefsStorage.getUserPrefsFilePath();
- }
-
- @Override
- public Optional readUserPrefs() throws DataConversionException, IOException {
- return userPrefsStorage.readUserPrefs();
- }
-
- @Override
- public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
- userPrefsStorage.saveUserPrefs(userPrefs);
- }
-
-
- // ================ AddressBook methods ==============================
-
- @Override
- public Path getAddressBookFilePath() {
- return addressBookStorage.getAddressBookFilePath();
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException, IOException {
- return readAddressBook(addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public Optional readAddressBook(Path filePath) throws DataConversionException, IOException {
- logger.fine("Attempting to read data from file: " + filePath);
- return addressBookStorage.readAddressBook(filePath);
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- logger.fine("Attempting to write to data file: " + filePath);
- addressBookStorage.saveAddressBook(addressBook, filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java
deleted file mode 100644
index 90bbf11de97..00000000000
--- a/src/main/java/seedu/address/ui/MainWindow.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package seedu.address.ui;
-
-import java.util.logging.Logger;
-
-import javafx.event.ActionEvent;
-import javafx.fxml.FXML;
-import javafx.scene.control.MenuItem;
-import javafx.scene.control.TextInputControl;
-import javafx.scene.input.KeyCombination;
-import javafx.scene.input.KeyEvent;
-import javafx.scene.layout.StackPane;
-import javafx.stage.Stage;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.Logic;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * The Main Window. Provides the basic application layout containing
- * a menu bar and space where other JavaFX elements can be placed.
- */
-public class MainWindow extends UiPart {
-
- private static final String FXML = "MainWindow.fxml";
-
- private final Logger logger = LogsCenter.getLogger(getClass());
-
- private Stage primaryStage;
- private Logic logic;
-
- // Independent Ui parts residing in this Ui container
- private PersonListPanel personListPanel;
- private ResultDisplay resultDisplay;
- private HelpWindow helpWindow;
-
- @FXML
- private StackPane commandBoxPlaceholder;
-
- @FXML
- private MenuItem helpMenuItem;
-
- @FXML
- private StackPane personListPanelPlaceholder;
-
- @FXML
- private StackPane resultDisplayPlaceholder;
-
- @FXML
- private StackPane statusbarPlaceholder;
-
- public MainWindow(Stage primaryStage, Logic logic) {
- super(FXML, primaryStage);
-
- // Set dependencies
- this.primaryStage = primaryStage;
- this.logic = logic;
-
- // Configure the UI
- setWindowDefaultSize(logic.getGuiSettings());
-
- setAccelerators();
-
- helpWindow = new HelpWindow();
- }
-
- public Stage getPrimaryStage() {
- return primaryStage;
- }
-
- private void setAccelerators() {
- setAccelerator(helpMenuItem, KeyCombination.valueOf("F1"));
- }
-
- /**
- * Sets the accelerator of a MenuItem.
- * @param keyCombination the KeyCombination value of the accelerator
- */
- private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) {
- menuItem.setAccelerator(keyCombination);
-
- /*
- * TODO: the code below can be removed once the bug reported here
- * https://bugs.openjdk.java.net/browse/JDK-8131666
- * is fixed in later version of SDK.
- *
- * According to the bug report, TextInputControl (TextField, TextArea) will
- * consume function-key events. Because CommandBox contains a TextField, and
- * ResultDisplay contains a TextArea, thus some accelerators (e.g F1) will
- * not work when the focus is in them because the key event is consumed by
- * the TextInputControl(s).
- *
- * For now, we add following event filter to capture such key events and open
- * help window purposely so to support accelerators even when focus is
- * in CommandBox or ResultDisplay.
- */
- getRoot().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
- if (event.getTarget() instanceof TextInputControl && keyCombination.match(event)) {
- menuItem.getOnAction().handle(new ActionEvent());
- event.consume();
- }
- });
- }
-
- /**
- * Fills up all the placeholders of this window.
- */
- void fillInnerParts() {
- personListPanel = new PersonListPanel(logic.getFilteredPersonList());
- personListPanelPlaceholder.getChildren().add(personListPanel.getRoot());
-
- resultDisplay = new ResultDisplay();
- resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot());
-
- StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath());
- statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot());
-
- CommandBox commandBox = new CommandBox(this::executeCommand);
- commandBoxPlaceholder.getChildren().add(commandBox.getRoot());
- }
-
- /**
- * Sets the default size based on {@code guiSettings}.
- */
- private void setWindowDefaultSize(GuiSettings guiSettings) {
- primaryStage.setHeight(guiSettings.getWindowHeight());
- primaryStage.setWidth(guiSettings.getWindowWidth());
- if (guiSettings.getWindowCoordinates() != null) {
- primaryStage.setX(guiSettings.getWindowCoordinates().getX());
- primaryStage.setY(guiSettings.getWindowCoordinates().getY());
- }
- }
-
- /**
- * Opens the help window or focuses on it if it's already opened.
- */
- @FXML
- public void handleHelp() {
- if (!helpWindow.isShowing()) {
- helpWindow.show();
- } else {
- helpWindow.focus();
- }
- }
-
- void show() {
- primaryStage.show();
- }
-
- /**
- * Closes the application.
- */
- @FXML
- private void handleExit() {
- GuiSettings guiSettings = new GuiSettings(primaryStage.getWidth(), primaryStage.getHeight(),
- (int) primaryStage.getX(), (int) primaryStage.getY());
- logic.setGuiSettings(guiSettings);
- helpWindow.hide();
- primaryStage.hide();
- }
-
- public PersonListPanel getPersonListPanel() {
- return personListPanel;
- }
-
- /**
- * Executes the command and returns the result.
- *
- * @see seedu.address.logic.Logic#execute(String)
- */
- private CommandResult executeCommand(String commandText) throws CommandException, ParseException {
- try {
- CommandResult commandResult = logic.execute(commandText);
- logger.info("Result: " + commandResult.getFeedbackToUser());
- resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());
-
- if (commandResult.isShowHelp()) {
- handleHelp();
- }
-
- if (commandResult.isExit()) {
- handleExit();
- }
-
- return commandResult;
- } catch (CommandException | ParseException e) {
- logger.info("Invalid command: " + commandText);
- resultDisplay.setFeedbackToUser(e.getMessage());
- throw e;
- }
- }
-}
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java
deleted file mode 100644
index 0684b088868..00000000000
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package seedu.address.ui;
-
-import java.util.Comparator;
-
-import javafx.fxml.FXML;
-import javafx.scene.control.Label;
-import javafx.scene.layout.FlowPane;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Region;
-import seedu.address.model.person.Person;
-
-/**
- * An UI component that displays information of a {@code Person}.
- */
-public class PersonCard extends UiPart {
-
- private static final String FXML = "PersonListCard.fxml";
-
- /**
- * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX.
- * As a consequence, UI elements' variable names cannot be set to such keywords
- * or an exception will be thrown by JavaFX during runtime.
- *
- * @see The issue on AddressBook level 4
- */
-
- public final Person person;
-
- @FXML
- private HBox cardPane;
- @FXML
- private Label name;
- @FXML
- private Label id;
- @FXML
- private Label phone;
- @FXML
- private Label address;
- @FXML
- private Label email;
- @FXML
- private FlowPane tags;
-
- public PersonCard(Person person, int displayedIndex) {
- super(FXML);
- this.person = person;
- id.setText(displayedIndex + ". ");
- name.setText(person.getName().fullName);
- phone.setText(person.getPhone().value);
- address.setText(person.getAddress().value);
- email.setText(person.getEmail().value);
- person.getTags().stream()
- .sorted(Comparator.comparing(tag -> tag.tagName))
- .forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof PersonCard)) {
- return false;
- }
-
- // state check
- PersonCard card = (PersonCard) other;
- return id.getText().equals(card.id.getText())
- && person.equals(card.person);
- }
-}
diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java
deleted file mode 100644
index 1328917096e..00000000000
--- a/src/main/java/seedu/address/ui/PersonListPanel.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package seedu.address.ui;
-
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.fxml.FXML;
-import javafx.scene.control.ListCell;
-import javafx.scene.control.ListView;
-import javafx.scene.layout.Region;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Panel containing the list of persons.
- */
-public class PersonListPanel extends UiPart {
- private static final String FXML = "PersonListPanel.fxml";
- private final Logger logger = LogsCenter.getLogger(PersonListPanel.class);
-
- @FXML
- private ListView personListView;
-
- public PersonListPanel(ObservableList personList) {
- super(FXML);
- personListView.setItems(personList);
- personListView.setCellFactory(listView -> new PersonListViewCell());
- }
-
- /**
- * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}.
- */
- class PersonListViewCell extends ListCell {
- @Override
- protected void updateItem(Person person, boolean empty) {
- super.updateItem(person, empty);
-
- if (empty || person == null) {
- setGraphic(null);
- setText(null);
- } else {
- setGraphic(new PersonCard(person, getIndex() + 1).getRoot());
- }
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/seedu/jelphabot/AppParameters.java
similarity index 93%
rename from src/main/java/seedu/address/AppParameters.java
rename to src/main/java/seedu/jelphabot/AppParameters.java
index ab552c398f3..07fa7f4a8c9 100644
--- a/src/main/java/seedu/address/AppParameters.java
+++ b/src/main/java/seedu/jelphabot/AppParameters.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.jelphabot;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -7,13 +7,14 @@
import java.util.logging.Logger;
import javafx.application.Application;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.FileUtil;
+import seedu.jelphabot.commons.core.LogsCenter;
+import seedu.jelphabot.commons.util.FileUtil;
/**
* Represents the parsed command-line parameters given to the application.
*/
public class AppParameters {
+
private static final Logger logger = LogsCenter.getLogger(AppParameters.class);
private Path configPath;
diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/jelphabot/Main.java
similarity index 97%
rename from src/main/java/seedu/address/Main.java
rename to src/main/java/seedu/jelphabot/Main.java
index 052a5068631..096264dfaa4 100644
--- a/src/main/java/seedu/address/Main.java
+++ b/src/main/java/seedu/jelphabot/Main.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.jelphabot;
import javafx.application.Application;
@@ -19,6 +19,7 @@
* to be the entry point of the application, we avoid this issue.
*/
public class Main {
+
public static void main(String[] args) {
Application.launch(MainApp.class, args);
}
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/jelphabot/MainApp.java
similarity index 63%
rename from src/main/java/seedu/address/MainApp.java
rename to src/main/java/seedu/jelphabot/MainApp.java
index e5cfb161b73..e7eb19afe08 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/jelphabot/MainApp.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.jelphabot;
import java.io.IOException;
import java.nio.file.Path;
@@ -7,29 +7,29 @@
import javafx.application.Application;
import javafx.stage.Stage;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.core.Version;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.ConfigUtil;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
-import seedu.address.logic.LogicManager;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.util.SampleDataUtil;
-import seedu.address.storage.AddressBookStorage;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.Storage;
-import seedu.address.storage.StorageManager;
-import seedu.address.storage.UserPrefsStorage;
-import seedu.address.ui.Ui;
-import seedu.address.ui.UiManager;
+import seedu.jelphabot.commons.core.Config;
+import seedu.jelphabot.commons.core.LogsCenter;
+import seedu.jelphabot.commons.core.Version;
+import seedu.jelphabot.commons.exceptions.DataConversionException;
+import seedu.jelphabot.commons.util.ConfigUtil;
+import seedu.jelphabot.commons.util.StringUtil;
+import seedu.jelphabot.logic.Logic;
+import seedu.jelphabot.logic.LogicManager;
+import seedu.jelphabot.model.JelphaBot;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.ModelManager;
+import seedu.jelphabot.model.ReadOnlyJelphaBot;
+import seedu.jelphabot.model.ReadOnlyUserPrefs;
+import seedu.jelphabot.model.UserPrefs;
+import seedu.jelphabot.model.util.SampleDataUtil;
+import seedu.jelphabot.storage.JelphaBotStorage;
+import seedu.jelphabot.storage.JsonJelphaBotStorage;
+import seedu.jelphabot.storage.JsonUserPrefsStorage;
+import seedu.jelphabot.storage.Storage;
+import seedu.jelphabot.storage.StorageManager;
+import seedu.jelphabot.storage.UserPrefsStorage;
+import seedu.jelphabot.ui.Ui;
+import seedu.jelphabot.ui.UiManager;
/**
* Runs the application.
@@ -48,7 +48,7 @@ public class MainApp extends Application {
@Override
public void init() throws Exception {
- logger.info("=============================[ Initializing AddressBook ]===========================");
+ logger.info("=============================[ Initializing JelphaBot ]===========================");
super.init();
AppParameters appParameters = AppParameters.parse(getParameters());
@@ -56,8 +56,9 @@ public void init() throws Exception {
UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
- AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
- storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ JelphaBotStorage jelphaBotStorage = new JsonJelphaBotStorage(
+ userPrefs.getJelphaBotFilePath(), userPrefs.getRemindersFilePath());
+ storage = new StorageManager(jelphaBotStorage, userPrefsStorage);
initLogging(config);
@@ -69,27 +70,34 @@ public void init() throws Exception {
}
/**
- * Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}.
- * The data from the sample address book will be used instead if {@code storage}'s address book is not found,
- * or an empty address book will be used instead if errors occur when reading {@code storage}'s address book.
+ * Returns a {@code ModelManager} with the data from {@code storage}'s task list and {@code userPrefs}.
+ * The data from the sample task list will be used instead if {@code storage}'s task list is not found,
+ * or an empty task list will be used instead if errors occur when reading {@code storage}'s task list.
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
- Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ Optional jelphaBotOptional;
+ Optional jelphaBotReminderOptional;
+ ReadOnlyJelphaBot initialData;
+ ReadOnlyJelphaBot initialReminderData;
try {
- addressBookOptional = storage.readAddressBook();
- if (!addressBookOptional.isPresent()) {
- logger.info("Data file not found. Will be starting with a sample AddressBook");
+ jelphaBotOptional = storage.readJelphaBot();
+ jelphaBotReminderOptional = storage.readJelphaBot(true);
+ if (!jelphaBotOptional.isPresent()) {
+ logger.info("Data file not found. Will be starting with a sample JelphaBot");
}
- initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
+ initialData = jelphaBotOptional.orElseGet(SampleDataUtil::getSampleJelphaBot);
+ initialReminderData = jelphaBotReminderOptional.orElseGet(SampleDataUtil::getSampleJelphaBot);
} catch (DataConversionException e) {
- logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Data file not in the correct format. Will be starting with an empty JelphaBot");
+ initialData = new JelphaBot();
+ initialReminderData = new JelphaBot();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Problem while reading from the file. Will be starting with an empty JelphaBot");
+ initialData = new JelphaBot();
+ initialReminderData = new JelphaBot();
}
+ initialData.setReminders(initialReminderData.getReminderList());
return new ModelManager(initialData, userPrefs);
}
@@ -151,7 +159,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
+ "Using default user prefs");
initializedPrefs = new UserPrefs();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
+ logger.warning("Problem while reading from the file. Will be starting with an empty JelphaBot");
initializedPrefs = new UserPrefs();
}
@@ -167,13 +175,14 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
@Override
public void start(Stage primaryStage) {
- logger.info("Starting AddressBook " + MainApp.VERSION);
+ logger.info("Starting JelphaBot " + MainApp.VERSION);
ui.start(primaryStage);
}
@Override
public void stop() {
- logger.info("============================ [ Stopping Address Book ] =============================");
+ logger.info("============================ [ Stopping JelphaBot ] =============================");
+
try {
storage.saveUserPrefs(model.getUserPrefs());
} catch (IOException e) {
diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/jelphabot/commons/core/Config.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/Config.java
rename to src/main/java/seedu/jelphabot/commons/core/Config.java
index 91145745521..c9de2e8a497 100644
--- a/src/main/java/seedu/address/commons/core/Config.java
+++ b/src/main/java/seedu/jelphabot/commons/core/Config.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.jelphabot.commons.core;
import java.nio.file.Path;
import java.nio.file.Paths;
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/jelphabot/commons/core/GuiSettings.java
similarity index 84%
rename from src/main/java/seedu/address/commons/core/GuiSettings.java
rename to src/main/java/seedu/jelphabot/commons/core/GuiSettings.java
index 5ace559ad15..1935852c453 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/jelphabot/commons/core/GuiSettings.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.jelphabot.commons.core;
import java.awt.Point;
import java.io.Serializable;
@@ -23,6 +23,12 @@ public GuiSettings() {
windowCoordinates = null; // null represent no coordinates
}
+ public GuiSettings(double windowWidth, double windowHeight) {
+ this.windowWidth = windowWidth;
+ this.windowHeight = windowHeight;
+ windowCoordinates = null;
+ }
+
public GuiSettings(double windowWidth, double windowHeight, int xPosition, int yPosition) {
this.windowWidth = windowWidth;
this.windowHeight = windowHeight;
@@ -53,8 +59,8 @@ public boolean equals(Object other) {
GuiSettings o = (GuiSettings) other;
return windowWidth == o.windowWidth
- && windowHeight == o.windowHeight
- && Objects.equals(windowCoordinates, o.windowCoordinates);
+ && windowHeight == o.windowHeight
+ && Objects.equals(windowCoordinates, o.windowCoordinates);
}
@Override
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/jelphabot/commons/core/LogsCenter.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/LogsCenter.java
rename to src/main/java/seedu/jelphabot/commons/core/LogsCenter.java
index 431e7185e76..fa98d348740 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/jelphabot/commons/core/LogsCenter.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.jelphabot.commons.core;
import java.io.IOException;
import java.util.Arrays;
@@ -18,7 +18,7 @@
public class LogsCenter {
private static final int MAX_FILE_COUNT = 5;
private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB
- private static final String LOG_FILE = "addressbook.log";
+ private static final String LOG_FILE = "jelphabot.log";
private static Level currentLogLevel = Level.INFO;
private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
private static FileHandler fileHandler;
diff --git a/src/main/java/seedu/jelphabot/commons/core/Messages.java b/src/main/java/seedu/jelphabot/commons/core/Messages.java
new file mode 100644
index 00000000000..6440adf36bd
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/commons/core/Messages.java
@@ -0,0 +1,33 @@
+package seedu.jelphabot.commons.core;
+
+/**
+ * Container for user visible messages.
+ */
+public class Messages {
+
+ public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command. Type 'help' for our user guide.";
+ public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
+ public static final String MESSAGE_INVALID_TASK_DISPLAYED_INDEX = "The task index provided is invalid";
+ public static final String MESSAGE_TASKS_LISTED_OVERVIEW = "%1$d tasks listed!";
+ public static final String MESSAGE_INVALID_DATE_FORMAT = "Invalid date format! "
+ + "Date should be one of these possible formats:\n"
+ + "[d-MMM-uuuu], E.g. 1-Jan-2020\n"
+ + "[d/MMM/uuuu], E.g. 1/Jan/2020\n"
+ + "[MMM-d-uuuu], E.g. Jan-1-2020\n"
+ + "[MMM/d/uuuu], E.g. Jan/1/2020";
+ public static final String MESSAGE_INVALID_YEARMONTH_FORMAT = "Invalid YearMonth format! YearMonth should be one "
+ + "of these possible formats:\n"
+ + "[MMM-uuuu], E.g. Jan-2020\n"
+ + "[MMM/uuuu], E.g. Jan/2020\n"
+ + "[uuuu/MMM], E.g. 2020/Jan\n"
+ + "[uuuu-MMM], E.g. 2020-Jan\n"
+ + "[uuuu-MM], E.g. 2020-01\n"
+ + "[uuuu/MM], E.g. 2020/01\n"
+ + "[uu-MM], E.g. 20-01\n"
+ + "[uu/MM], E.g. 20/01";
+ public static final String MESSAGE_COMPLIMENT = "Good work! (:";
+ public static final String MESSAGE_ENCOURAGEMENT = "You can do better than this!";
+ public static final String MESSAGE_CRITICISM = "Do better! You have many unfinished tasks that are past their"
+ + " due date!";
+ public static final String MESSAGE_NO_TIMERS = "There are no tasks being timed at the moment.";
+}
diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/jelphabot/commons/core/Version.java
similarity index 96%
rename from src/main/java/seedu/address/commons/core/Version.java
rename to src/main/java/seedu/jelphabot/commons/core/Version.java
index e117f91b3b2..0997baabbaf 100644
--- a/src/main/java/seedu/address/commons/core/Version.java
+++ b/src/main/java/seedu/jelphabot/commons/core/Version.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.jelphabot.commons.core;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -61,7 +61,7 @@ public static Version fromString(String versionString) throws IllegalArgumentExc
return new Version(Integer.parseInt(versionMatcher.group(1)),
Integer.parseInt(versionMatcher.group(2)),
Integer.parseInt(versionMatcher.group(3)),
- versionMatcher.group(4) == null ? false : true);
+ versionMatcher.group(4) != null);
}
@JsonValue
diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/seedu/jelphabot/commons/core/index/Index.java
similarity index 91%
rename from src/main/java/seedu/address/commons/core/index/Index.java
rename to src/main/java/seedu/jelphabot/commons/core/index/Index.java
index 19536439c09..921165a30ca 100644
--- a/src/main/java/seedu/address/commons/core/index/Index.java
+++ b/src/main/java/seedu/jelphabot/commons/core/index/Index.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core.index;
+package seedu.jelphabot.commons.core.index;
/**
* Represents a zero-based or one-based index.
@@ -10,15 +10,14 @@
*/
public class Index {
private int zeroBasedIndex;
-
/**
* Index can only be created by calling {@link Index#fromZeroBased(int)} or
* {@link Index#fromOneBased(int)}.
*/
private Index(int zeroBasedIndex) {
- if (zeroBasedIndex < 0) {
- throw new IndexOutOfBoundsException();
- }
+ //if (zeroBasedIndex < 0) {
+ // throw new IndexOutOfBoundsException();
+ //}
this.zeroBasedIndex = zeroBasedIndex;
}
diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/seedu/jelphabot/commons/exceptions/DataConversionException.java
similarity index 83%
rename from src/main/java/seedu/address/commons/exceptions/DataConversionException.java
rename to src/main/java/seedu/jelphabot/commons/exceptions/DataConversionException.java
index 1f689bd8e3f..80efb778451 100644
--- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java
+++ b/src/main/java/seedu/jelphabot/commons/exceptions/DataConversionException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.jelphabot.commons.exceptions;
/**
* Represents an error during conversion of data from one format to another
diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/jelphabot/commons/exceptions/IllegalValueException.java
similarity index 92%
rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
rename to src/main/java/seedu/jelphabot/commons/exceptions/IllegalValueException.java
index 19124db485c..8bd0279b7f1 100644
--- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
+++ b/src/main/java/seedu/jelphabot/commons/exceptions/IllegalValueException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.jelphabot.commons.exceptions;
/**
* Signals that some given data does not fulfill some constraints.
diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/seedu/jelphabot/commons/util/AppUtil.java
similarity index 93%
rename from src/main/java/seedu/address/commons/util/AppUtil.java
rename to src/main/java/seedu/jelphabot/commons/util/AppUtil.java
index da90201dfd6..b24a6b2bf13 100644
--- a/src/main/java/seedu/address/commons/util/AppUtil.java
+++ b/src/main/java/seedu/jelphabot/commons/util/AppUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.jelphabot.commons.util;
import static java.util.Objects.requireNonNull;
import javafx.scene.image.Image;
-import seedu.address.MainApp;
+import seedu.jelphabot.MainApp;
/**
* A container for App specific utility functions
@@ -36,4 +36,5 @@ public static void checkArgument(Boolean condition, String errorMessage) {
throw new IllegalArgumentException(errorMessage);
}
}
+
}
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/jelphabot/commons/util/CollectionUtil.java
similarity index 96%
rename from src/main/java/seedu/address/commons/util/CollectionUtil.java
rename to src/main/java/seedu/jelphabot/commons/util/CollectionUtil.java
index eafe4dfd681..43257cf1e1f 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/jelphabot/commons/util/CollectionUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.jelphabot.commons.util;
import static java.util.Objects.requireNonNull;
diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/seedu/jelphabot/commons/util/ConfigUtil.java
similarity index 76%
rename from src/main/java/seedu/address/commons/util/ConfigUtil.java
rename to src/main/java/seedu/jelphabot/commons/util/ConfigUtil.java
index f7f8a2bd44c..55fc1585dbf 100644
--- a/src/main/java/seedu/address/commons/util/ConfigUtil.java
+++ b/src/main/java/seedu/jelphabot/commons/util/ConfigUtil.java
@@ -1,11 +1,11 @@
-package seedu.address.commons.util;
+package seedu.jelphabot.commons.util;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.jelphabot.commons.core.Config;
+import seedu.jelphabot.commons.exceptions.DataConversionException;
/**
* A class for accessing the Config File.
diff --git a/src/main/java/seedu/jelphabot/commons/util/DateUtil.java b/src/main/java/seedu/jelphabot/commons/util/DateUtil.java
new file mode 100644
index 00000000000..679a7bd1081
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/commons/util/DateUtil.java
@@ -0,0 +1,98 @@
+package seedu.jelphabot.commons.util;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.function.Predicate;
+
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.predicates.TaskDueAfterDatePredicate;
+import seedu.jelphabot.model.task.predicates.TaskDueBeforeDatePredicate;
+
+/**
+ * Helper functions for handling dates.
+ */
+public class DateUtil {
+ /**
+ * Get the date at the time the method is called.
+ *
+ * @return LocalDate representing the current day's date.
+ */
+ public static LocalDate getDateToday() {
+ return LocalDate.now();
+ }
+
+ /**
+ * Get the date at the time one day after the method is called.
+ *
+ * @return LocalDate representing the next day's date.
+ */
+ public static LocalDate getDateTomorrow() {
+ return LocalDate.now().plusDays(1);
+
+ }
+
+ /**
+ * Get the date at the time one week after the method is called.
+ *
+ * @return LocalDate representing the date one week from now.
+ */
+ public static LocalDate getDateNextWeek() {
+ return LocalDate.now().plusWeeks(1);
+ }
+
+ /**
+ * Convert a Java7 Date object to a Java8 LocalDate object representing the same instant in time.
+ *
+ * @param date Java7 Date object to be converted.
+ * @return LocalDate with the same date as the input Date.
+ */
+ public static LocalDate dateToLocalDate(Date date) {
+ return date.toInstant()
+ .atZone(ZoneId.systemDefault())
+ .toLocalDate();
+ }
+
+ /**
+ * Convert a Java7 Date object to a Java8 LocalDateTime object representing the same instant in time.
+ *
+ * @param date Java7 Date object to be converted.
+ * @return LocalDate with the same date and time as the input Date.
+ */
+ public static LocalDateTime dateToLocalDateTime(Date date) {
+ return date.toInstant()
+ .atZone(ZoneId.systemDefault())
+ .toLocalDateTime();
+ }
+
+ /**
+ * @return a predicate which filters tasks with a due date before the instant the method was called.
+ */
+ public static Predicate getOverduePredicate() {
+ return new TaskDueBeforeDatePredicate();
+ }
+
+ /**
+ * @return a predicate which filters tasks with a due date the same day as the instant the method was called.
+ */
+ public static Predicate getDueTodayPredicate() {
+ return new TaskDueAfterDatePredicate().and(new TaskDueBeforeDatePredicate(getDateTomorrow()));
+ }
+
+ /**
+ * @return a predicate which filters tasks with a due date between one and seven days after the instant the
+ * method was called.
+ */
+ public static Predicate getDueThisWeekPredicate() {
+ return new TaskDueAfterDatePredicate(getDateTomorrow()).and(new TaskDueBeforeDatePredicate(getDateNextWeek()));
+ }
+
+ /**
+ * @return a predicate which filters tasks with a due date more than seven days after the instant the
+ * method was called.
+ */
+ public static Predicate getDueSomedayPredicate() {
+ return new TaskDueAfterDatePredicate(getDateNextWeek());
+ }
+}
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/jelphabot/commons/util/FileUtil.java
similarity index 95%
rename from src/main/java/seedu/address/commons/util/FileUtil.java
rename to src/main/java/seedu/jelphabot/commons/util/FileUtil.java
index b1e2767cdd9..3f6a586033b 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/jelphabot/commons/util/FileUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.jelphabot.commons.util;
import java.io.IOException;
import java.nio.file.Files;
@@ -18,8 +18,9 @@ public static boolean isFileExists(Path file) {
}
/**
- * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String)},
+ * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String, String...)},
* otherwise returns false.
+ *
* @param path A string representing the file path. Cannot be null.
*/
public static boolean isValidPath(String path) {
diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/jelphabot/commons/util/JsonUtil.java
similarity index 97%
rename from src/main/java/seedu/address/commons/util/JsonUtil.java
rename to src/main/java/seedu/jelphabot/commons/util/JsonUtil.java
index 8ef609f055d..1450b486f03 100644
--- a/src/main/java/seedu/address/commons/util/JsonUtil.java
+++ b/src/main/java/seedu/jelphabot/commons/util/JsonUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.jelphabot.commons.util;
import static java.util.Objects.requireNonNull;
@@ -20,8 +20,8 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.jelphabot.commons.core.LogsCenter;
+import seedu.jelphabot.commons.exceptions.DataConversionException;
/**
* Converts a Java object instance to JSON and vice versa
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/jelphabot/commons/util/StringUtil.java
similarity index 89%
rename from src/main/java/seedu/address/commons/util/StringUtil.java
rename to src/main/java/seedu/jelphabot/commons/util/StringUtil.java
index 61cc8c9a1cb..ec5a5a2bab7 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/jelphabot/commons/util/StringUtil.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.jelphabot.commons.util;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.jelphabot.commons.util.AppUtil.checkArgument;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -60,7 +60,8 @@ public static boolean isNonZeroUnsignedInteger(String s) {
try {
int value = Integer.parseInt(s);
- return value > 0 && !s.startsWith("+"); // "+1" is successfully parsed by Integer#parseInt(String)
+ //return value > 0 && !s.startsWith("+"); // "+1" is successfully parsed by Integer#parseInt(String)
+ return !s.startsWith("+");
} catch (NumberFormatException nfe) {
return false;
}
diff --git a/src/main/java/seedu/jelphabot/logic/Logic.java b/src/main/java/seedu/jelphabot/logic/Logic.java
new file mode 100644
index 00000000000..adb601d715f
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/Logic.java
@@ -0,0 +1,126 @@
+package seedu.jelphabot.logic;
+
+import java.nio.file.Path;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.jelphabot.commons.core.GuiSettings;
+import seedu.jelphabot.logic.commands.CommandResult;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.ReadOnlyJelphaBot;
+import seedu.jelphabot.model.productivity.ProductivityList;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderShowsTask;
+import seedu.jelphabot.model.summary.SummaryList;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.GroupedTaskList;
+import seedu.jelphabot.model.task.tasklist.GroupedTaskList.Category;
+import seedu.jelphabot.model.task.tasklist.PinnedTaskList;
+
+/**
+ * API of the Logic component
+ */
+public interface Logic {
+ /**
+ * Executes the command and returns the result.
+ *
+ * @param commandText The command as entered by the user.
+ * @return the result of the command execution.
+ * @throws CommandException If an error occurs during command execution.
+ * @throws ParseException If an error occurs during parsing.
+ */
+ CommandResult execute(String commandText) throws CommandException, ParseException;
+
+ /**
+ * Returns the JelphaBot.
+ *
+ * @see seedu.jelphabot.model.Model#getJelphaBot()
+ */
+ ReadOnlyJelphaBot getJelphaBot();
+
+ /**
+ * Returns an unmodifiable view of the filtered list of tasks.
+ */
+ ObservableList getFilteredTaskList();
+
+ /**
+ * Returns an unmodifiable view of the filtered list of tasks in the Calendar.
+ */
+ ObservableList getFilteredCalendarTaskList();
+
+ /**
+ * Returns an unmodifiable view of the completed tasks in the task list.
+ */
+ ObservableList getFilteredByCompleteTaskList();
+
+ /**
+ * Returns an unmodifiable view of the tasks that were completed within the day.
+ */
+ ObservableList getFilteredByCompletedTodayTaskList();
+
+ /**
+ * Returns an unmodifiable view of the incomplete tasks in the task list.
+ */
+ ObservableList getFilteredByIncompleteTaskList();
+
+ /**
+ * Returns a wrapper for categorised tasks in the task list.
+ */
+ GroupedTaskList getGroupedTaskList(Category category);
+
+ /**
+ * Returns an unmodifiable view of the incomplete tasks that are due today in
+ * the task list.
+ */
+ ObservableList getFilteredByIncompleteDueTodayTaskList();
+
+ /**
+ * Returns an unmodifiable view of the incomplete tasks that are due soon,
+ * as specified by the user.
+ */
+ ObservableList getFilteredByReminder();
+ /**
+ * Returns an unmodifiable view of the user's productivity.
+ */
+ ProductivityList getProductivityList();
+
+ ObservableList getReminderList();
+
+ ObservableList getReminderShowsTaskList();
+
+ /**
+ * Returns an unmodifiable view of the user's summary.
+ */
+ SummaryList getSummaryList();
+ /**
+ * Returns the user prefs' jelphabot file path.
+ */
+ Path getJelphaBotFilePath();
+
+ Path getRemindersFilePath();
+
+ /**
+ * Returns the user prefs' GUI settings.
+ */
+ GuiSettings getGuiSettings();
+
+ /**
+ * Returns the GUI settings for a popup window
+ */
+ GuiSettings getPopUpWindowGuiSettings();
+
+ /**
+ * Set the user prefs' GUI settings.
+ */
+ void setGuiSettings(GuiSettings guiSettings);
+
+ /**
+ * Updates the filter of the filtered calendar task list to filter by the given {@code predicate}.
+ *
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredCalendarTaskList(Predicate predicate);
+
+ PinnedTaskList getPinnedTaskList();
+}
diff --git a/src/main/java/seedu/jelphabot/logic/LogicManager.java b/src/main/java/seedu/jelphabot/logic/LogicManager.java
new file mode 100644
index 00000000000..590324609c7
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/LogicManager.java
@@ -0,0 +1,190 @@
+package seedu.jelphabot.logic;
+
+import static seedu.jelphabot.commons.util.DateUtil.getDueTodayPredicate;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import seedu.jelphabot.commons.core.GuiSettings;
+import seedu.jelphabot.commons.core.LogsCenter;
+import seedu.jelphabot.logic.commands.Command;
+import seedu.jelphabot.logic.commands.CommandResult;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.logic.parser.JelphaBotParser;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.ReadOnlyJelphaBot;
+import seedu.jelphabot.model.productivity.ProductivityList;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderShowsTask;
+import seedu.jelphabot.model.summary.SummaryList;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.predicates.ReminderPredicate;
+import seedu.jelphabot.model.task.predicates.TaskCompletedWithinDayPredicate;
+import seedu.jelphabot.model.task.predicates.TaskIsCompletedPredicate;
+import seedu.jelphabot.model.task.predicates.TaskIsIncompletePredicate;
+import seedu.jelphabot.model.task.tasklist.GroupedTaskList;
+import seedu.jelphabot.model.task.tasklist.PinnedTaskList;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+import seedu.jelphabot.storage.Storage;
+
+/**
+ * The main LogicManager of the app.
+ */
+public class LogicManager implements Logic {
+
+ public static final String FILE_OPS_ERROR_MESSAGE = "Could not save data to file: ";
+ private final Logger logger = LogsCenter.getLogger(LogicManager.class);
+
+ private final Model model;
+ private final Storage storage;
+ private final JelphaBotParser jelphaBotParser;
+
+ public LogicManager(Model model, Storage storage) {
+ this.model = model;
+ this.storage = storage;
+ jelphaBotParser = new JelphaBotParser();
+ }
+
+ @Override
+ public CommandResult execute(String commandText) throws CommandException, ParseException {
+ logger.info("----------------[USER COMMAND][" + commandText + "]");
+
+ CommandResult commandResult;
+ Command command = jelphaBotParser.parseCommand(commandText);
+ commandResult = command.execute(model);
+
+ try {
+ storage.saveJelphaBot(model.getJelphaBot());
+ //storage.saveJelphaBot(model.getJelphaBot(), true);
+ } catch (IOException ioe) {
+ throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
+ }
+
+ return commandResult;
+ }
+
+ @Override
+ public ObservableList getReminderList() {
+ return model.getFilteredReminderList();
+ }
+
+ @Override
+ public ObservableList getReminderShowsTaskList() {
+ model.updateReminderShowsTask();
+ return model.getReminderShowsTaskList();
+ }
+
+ @Override
+ public ReadOnlyJelphaBot getJelphaBot() {
+ return model.getJelphaBot();
+ }
+
+ @Override
+ public ObservableList getFilteredTaskList() {
+ return model.getFilteredTaskList();
+ }
+
+ @Override
+ public ObservableList getFilteredCalendarTaskList() {
+ return model.getFilteredCalendarTaskList();
+ }
+
+ @Override
+ public ObservableList getFilteredByCompleteTaskList() {
+ ObservableList filteredTasks = model.getFilteredTaskList();
+ TaskIsCompletedPredicate predicate = new TaskIsCompletedPredicate();
+ return new FilteredList<>(filteredTasks, predicate);
+ }
+
+ @Override
+ public ObservableList getFilteredByCompletedTodayTaskList() {
+ ObservableList filteredTasks = model.getFilteredTaskList();
+ TaskCompletedWithinDayPredicate pred = new TaskCompletedWithinDayPredicate();
+ return new FilteredList<>(filteredTasks, pred);
+ }
+
+ public ObservableList getFilteredByReminder() {
+ ViewTaskList taskList = model.getLastShownList();
+ List reminderList = model.getReminderListFromJelphaBot();
+ ReminderPredicate reminderPredicate = new ReminderPredicate(taskList, reminderList);
+ return model.getFilteredTaskList().filtered(reminderPredicate);
+ }
+
+ @Override
+ public ObservableList getFilteredByIncompleteTaskList() {
+ ObservableList filteredTasks = model.getFilteredTaskList();
+ TaskIsIncompletePredicate taskIncompletePredicate = new TaskIsIncompletePredicate();
+ return new FilteredList<>(filteredTasks, taskIncompletePredicate);
+ }
+
+ //@@author eedenong
+ public ObservableList getFilteredByIncompleteDueTodayTaskList() {
+ ObservableList filteredTasks = model.getFilteredTaskList();
+ TaskIsIncompletePredicate taskIncompletePredicate = new TaskIsIncompletePredicate();
+ FilteredList filteredIncompleteList = new FilteredList<>(filteredTasks, taskIncompletePredicate);
+ return new FilteredList<>(filteredIncompleteList, getDueTodayPredicate());
+ }
+
+ // @@author
+
+ @Override
+ public GroupedTaskList getGroupedTaskList(GroupedTaskList.Category category) {
+ return model.getGroupedTaskList(category);
+ }
+
+ @Override
+ public PinnedTaskList getPinnedTaskList() {
+ return model.getPinnedTaskList();
+ }
+
+ @Override
+ public ProductivityList getProductivityList() {
+ return model.getProductivityList();
+ }
+
+ @Override
+ public SummaryList getSummaryList() {
+ return model.getSummaryList();
+ }
+
+ @Override
+ public Path getJelphaBotFilePath() {
+ return model.getJelphaBotFilePath();
+ }
+
+ @Override
+ public Path getRemindersFilePath() {
+ return model.getRemindersFilePath();
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ return model.getGuiSettings();
+ }
+
+ @Override
+ public GuiSettings getPopUpWindowGuiSettings() {
+ return model.getPopUpWindowGuiSettings();
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ model.setGuiSettings(guiSettings);
+ }
+
+ /**
+ * Updates the filter of the filtered calendar task list to filter by the given {@code predicate}.
+ *
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ @Override
+ public void updateFilteredCalendarTaskList(Predicate predicate) {
+ model.updateFilteredCalendarTaskList(predicate);
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/AddCommand.java b/src/main/java/seedu/jelphabot/logic/commands/AddCommand.java
new file mode 100644
index 00000000000..e9433053261
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/AddCommand.java
@@ -0,0 +1,67 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DATETIME;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_MODULE_CODE;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_TAG;
+
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.summary.Summary;
+import seedu.jelphabot.model.task.Task;
+
+/**
+ * Adds a Task to the task list.
+ */
+public class AddCommand extends Command {
+
+ public static final String COMMAND_WORD = "add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to the task list.\n"
+ + "Parameters: \n"
+ + " " + PREFIX_DESCRIPTION + "DESCRIPTION\n"
+ + " " + PREFIX_DATETIME + "DATETIME in format MMM-dd-YYYY HH mm\n"
+ + " " + PREFIX_MODULE_CODE + "MODULE_CODE\n"
+ + " " + "[" + PREFIX_PRIORITY + "PRIORITY (-1, 0 or 1), DEFAULTS TO 1]\n"
+ + " " + "[" + PREFIX_TAG + "TAG]...\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_DESCRIPTION + "Assignment 1 " + PREFIX_DATETIME + "Jan-01-2020 23 59 "
+ + PREFIX_MODULE_CODE + "CS3230 " + PREFIX_PRIORITY + "1\n";
+
+ public static final String MESSAGE_SUCCESS = "New task added: %1$s";
+ public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task list";
+
+ private final Task toAdd;
+
+ /**
+ * Creates an AddCommand to add the specified {@code Task}
+ */
+ public AddCommand(Task task) {
+ requireNonNull(task);
+ toAdd = task;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasTask(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TASK);
+ }
+
+ model.addTask(toAdd);
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), true, false, false));
+ model.setSummary(new Summary(model.getFilteredTaskList()));
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddCommand // instanceof handles nulls
+ && toAdd.equals(((AddCommand) other).toAdd));
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/CalendarCommand.java b/src/main/java/seedu/jelphabot/logic/commands/CalendarCommand.java
new file mode 100644
index 00000000000..1bdb3b81469
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/CalendarCommand.java
@@ -0,0 +1,102 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.time.LocalDate;
+import java.time.YearMonth;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.calendar.CalendarDate;
+import seedu.jelphabot.model.task.predicates.TaskDueWithinDayPredicate;
+
+//@@author alam8064
+/**
+ * Lists all tasks in task list whose date corresponds with the specified date.
+ * Shows the tasks that are due on the specified date.
+ */
+public class CalendarCommand extends Command {
+
+ public static final String COMMAND_WORD = "calendar";
+ public static final String COMMAND_SHORTCUT_UPPER = ":C";
+ public static final String COMMAND_SHORTCUT_LOWER = ":c";
+
+ //update this
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all task that is under the due date specified.\n"
+ + "Parameters: DATE \n"
+ + "Example: " + COMMAND_WORD + " Jan-1-2020";
+
+ public static final String MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT = "Switched to calendar panel.";
+
+ public static final String MESSAGE_SWITCH_CALENDAR_VIEW_ACKNOWLEDGEMENT = "Switched calendar panel to : %s, %s";
+ public static final String MESSAGE_SWITCH_CALENDAR_TODAY_ACKNOWLEDGEMENT = "Switched calendar panel back to : "
+ + "%s, %s. Displaying all your tasks"
+ + " that are due today!";
+
+ private final TaskDueWithinDayPredicate predicate;
+ private final YearMonth yearMonth;
+
+ private boolean isToday;
+ private boolean isMonth;
+
+ public CalendarCommand() {
+ predicate = null;
+ yearMonth = null;
+ }
+
+ public CalendarCommand(TaskDueWithinDayPredicate predicate) {
+ this.predicate = predicate;
+ yearMonth = null;
+ }
+
+ public CalendarCommand(YearMonth yearMonth) {
+ LocalDate firstDayOfMonth = yearMonth.atDay(1);
+ this.predicate = new TaskDueWithinDayPredicate(firstDayOfMonth);
+ this.yearMonth = yearMonth;
+ isMonth = true;
+ }
+
+ public CalendarCommand(TaskDueWithinDayPredicate predicate, boolean today) {
+ this.predicate = predicate;
+ this.isToday = today;
+ yearMonth = null;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ if (predicate == null && yearMonth == null) {
+ return new CommandResult(MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT, false, false).isShowCalendar();
+ } else if (isToday) { //switch calendar view and task list for today
+ requireNonNull(model);
+ model.updateFilteredCalendarTaskList(predicate);
+ LocalDate date = predicate.getDate();
+ return new CommandResult(String.format(MESSAGE_SWITCH_CALENDAR_TODAY_ACKNOWLEDGEMENT,
+ CalendarDate.getMonthNameOf(date.getMonthValue()), date.getYear()), null, null);
+ } else if (isMonth) { //switch calendar view
+ requireNonNull(model);
+ model.updateFilteredCalendarTaskList(predicate);
+ return new CommandResult(String.format(MESSAGE_SWITCH_CALENDAR_VIEW_ACKNOWLEDGEMENT,
+ CalendarDate.getMonthNameOf(yearMonth.getMonthValue()), yearMonth.getYear()), null, yearMonth);
+ } else { //switch task list for specific dates
+ requireNonNull(model);
+ model.updateFilteredCalendarTaskList(predicate);
+ LocalDate date = predicate.getDate();
+ return new CommandResult(
+ String.format(Messages.MESSAGE_TASKS_LISTED_OVERVIEW,
+ model.getFilteredCalendarTaskList().size()), date, null);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof CalendarCommand // instanceof handles nulls
+ && predicate.equals(((CalendarCommand) other).predicate)
+ && yearMonth == null && ((CalendarCommand) other).yearMonth == null)
+ || (other instanceof CalendarCommand // instanceof handles nulls
+ && predicate.equals(((CalendarCommand) other).predicate)
+ && yearMonth.equals(((CalendarCommand) other).yearMonth)); // state check
+ }
+
+}
+
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ClearCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ClearCommand.java
new file mode 100644
index 00000000000..f0d6a7224af
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ClearCommand.java
@@ -0,0 +1,32 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.jelphabot.model.JelphaBot;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.summary.Summary;
+
+/**
+ * Clears the task list.
+ */
+public class ClearCommand extends Command {
+
+ public static final String COMMAND_WORD = "clear";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Clears all tasks in the list permanently.\n"
+ + "Example: " + COMMAND_WORD;
+
+ public static final String MESSAGE_SUCCESS = "JelphaBot has been cleared!";
+
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.setJelphaBot(new JelphaBot());
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), true, true, true));
+ model.setSummary(new Summary(model.getFilteredTaskList()));
+
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/jelphabot/logic/commands/Command.java
similarity index 78%
rename from src/main/java/seedu/address/logic/commands/Command.java
rename to src/main/java/seedu/jelphabot/logic/commands/Command.java
index 64f18992160..e7df58da10c 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/jelphabot/logic/commands/Command.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.commands;
+package seedu.jelphabot.logic.commands;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
/**
* Represents a command with hidden internal logic and the ability to be executed.
diff --git a/src/main/java/seedu/jelphabot/logic/commands/CommandResult.java b/src/main/java/seedu/jelphabot/logic/commands/CommandResult.java
new file mode 100644
index 00000000000..efba7505586
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/CommandResult.java
@@ -0,0 +1,173 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.time.LocalDate;
+import java.time.YearMonth;
+import java.util.Objects;
+
+/**
+ * Represents the result of a command execution.
+ */
+public class CommandResult {
+
+ private final String feedbackToUser;
+
+ /**
+ * Help information should be shown to the user.
+ */
+ private final boolean showHelp;
+
+ /**
+ * The application should exit.
+ */
+ private final boolean exit;
+
+ private boolean calendarCommand;
+ private LocalDate date;
+ private YearMonth yearMonth;
+ private SwitchTab toSwitch = SwitchTab.STAY_ON_CURRENT;
+
+ /**
+ * Constructs a {@code CommandResult} with the specified fields.
+ */
+ public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) {
+ this.feedbackToUser = requireNonNull(feedbackToUser);
+ this.showHelp = showHelp;
+ this.exit = exit;
+ }
+
+ /**
+ * Constructs a {@code CommandResult} with the specified {@code feedbackToUser},
+ * and other fields set to their default value.
+ */
+ public CommandResult(String feedbackToUser) {
+ this(feedbackToUser, false, false);
+ }
+
+ public CommandResult(String feedbackToUser, LocalDate date, YearMonth yearMonth) {
+ this(feedbackToUser, false, false);
+ this.date = date;
+ this.yearMonth = yearMonth;
+ this.calendarCommand = true;
+ }
+
+ /**
+ * The application should switch to the Task List tab
+ * @return Sets the "switch to window" flag to Task List.
+ */
+ public CommandResult isShowDateTaskList() {
+ this.toSwitch = SwitchTab.TASK_LIST_DATE;
+ return this;
+ }
+
+ /**
+ * The application should switch to the Task List tab
+ * @return Sets the "switch to window" flag to Task List.
+ */
+ public CommandResult isShowModuleTaskList() {
+ this.toSwitch = SwitchTab.TASK_LIST_MODULE;
+ return this;
+ }
+
+ public String getFeedbackToUser() {
+ return feedbackToUser;
+ }
+
+ public LocalDate getDate() {
+ return date;
+ }
+
+ public YearMonth getYearMonth() {
+ return yearMonth;
+ }
+
+ public boolean isCalendarCommand() {
+ return calendarCommand;
+ }
+
+ public boolean isShowHelp() {
+ return showHelp;
+ }
+
+ public boolean isExit() {
+ return exit;
+ }
+
+ /**
+ * The application should switch to the productivity tab.
+ * @return Sets the "toSwitch" flag to Productivity.
+ */
+ public CommandResult isShowProductivity() {
+ this.toSwitch = SwitchTab.PRODUCTIVITY;
+ return this;
+ }
+
+ /**
+ * The application should switch to the Calendar tab.
+ * @return Sets the "toSwitch" flag to Calendar.
+ */
+ public CommandResult isShowCalendar() {
+ this.toSwitch = SwitchTab.CALENDAR;
+ return this;
+ }
+
+ /**
+ * The application should switch to the Summary tab.
+ * @return Sets the "toSwitch" flag to Summary.
+ */
+ public CommandResult isShowSummary() {
+ this.toSwitch = SwitchTab.SUMMARY;
+ return this;
+ }
+
+ /**
+ * The application should switch to the Calendar tab.
+ * @return Sets the "toSwitch" flag to Calendar.
+ */
+ public CommandResult isShowReminder() {
+ this.toSwitch = SwitchTab.REMINDER;
+ return this;
+ }
+
+ public SwitchTab getTabSwitch() {
+ return toSwitch;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof CommandResult)) {
+ return false;
+ }
+
+ CommandResult otherCommandResult = (CommandResult) other;
+ return feedbackToUser.equals(otherCommandResult.feedbackToUser)
+ && showHelp == otherCommandResult.showHelp
+ && exit == otherCommandResult.exit
+ && toSwitch == otherCommandResult.toSwitch;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(feedbackToUser, showHelp, exit, toSwitch);
+ }
+
+ /**
+ * Enum representing switch that indicates if the command should switch to another window.
+ */
+ public enum SwitchTab {
+ CALENDAR,
+ PRODUCTIVITY,
+ SUMMARY,
+ TASK_LIST_DATE,
+ TASK_LIST_MODULE,
+ STAY_ON_CURRENT,
+ REMINDER
+ }
+
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/DeleteCommand.java b/src/main/java/seedu/jelphabot/logic/commands/DeleteCommand.java
new file mode 100644
index 00000000000..d103e8831fb
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/DeleteCommand.java
@@ -0,0 +1,77 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.logging.Logger;
+
+import seedu.jelphabot.commons.core.LogsCenter;
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.summary.Summary;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Deletes a task identified using it's displayed index from the task list.
+ */
+public class DeleteCommand extends Command {
+
+ public static final String COMMAND_WORD = "delete";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the task identified by the index number used in the "
+ + "displayed task list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n" + "Example: "
+ + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_TASK_SUCCESS = "Deleted Task: %1$s";
+ public static final String MESSAGE_DELETE_RUNNING_TASK = "Deleted Task with running timer: %1$s ";
+
+ public static final String REMINDER_ASSOCIATED_WITH_TASK = DeleteReminderCommand.MESSAGE_DELETE_REMINDER_SUCCESS;
+
+ private static final Logger logger = LogsCenter.getLogger(DeleteCommand.class);
+
+ private final Index targetIndex;
+
+ public DeleteCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ ViewTaskList lastShownList = model.getLastShownList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size() || targetIndex.getZeroBased() < 0) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToDelete = lastShownList.get(targetIndex.getZeroBased());
+ try {
+ CommandResult fromDeleteReminderCommand = new DeleteReminderCommand(targetIndex).execute(model);
+ } catch (CommandException ce) {
+ logger.info(REMINDER_ASSOCIATED_WITH_TASK);
+ }
+ model.deleteTask(taskToDelete);
+ model.updateDeletedReminders(targetIndex);
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), true, true, true));
+ model.setSummary(new Summary(model.getFilteredTaskList()));
+
+ if (taskToDelete.isBeingTimed()) {
+ return new CommandResult(String.format(MESSAGE_DELETE_RUNNING_TASK, taskToDelete));
+ } else {
+ return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, taskToDelete));
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/DeleteReminderCommand.java b/src/main/java/seedu/jelphabot/logic/commands/DeleteReminderCommand.java
new file mode 100644
index 00000000000..45748d45440
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/DeleteReminderCommand.java
@@ -0,0 +1,66 @@
+//@@author yapdianhao
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Deletes a reminder according to the task's index.
+ */
+public class DeleteReminderCommand extends Command {
+
+ public static final String COMMAND_WORD = "delrem";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the reminder identified by the index number"
+ + " of the task used in the displayed task list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_REMINDER_SUCCESS = "Deleted Reminder for task %1$s";
+
+ public static final String MESSAGE_DELETE_REMINDER_FAILURE = "Reminder not found!";
+
+ private final Index targetIndex;
+
+ public DeleteReminderCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ ViewTaskList lastShownList = model.getLastShownList();
+ List reminderList = model.getFilteredReminderList();
+ if (targetIndex.getZeroBased() < 0 || targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ Reminder toDelete = null;
+ for (Reminder reminder : reminderList) {
+ if (reminder.getIndex().equals(targetIndex)) {
+ toDelete = reminder;
+ }
+ }
+ if (toDelete == null) {
+ throw new CommandException(MESSAGE_DELETE_REMINDER_FAILURE);
+ } else {
+ model.deleteReminder(toDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_REMINDER_SUCCESS, this.targetIndex.getOneBased()));
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteReminderCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteReminderCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/DoneCommand.java b/src/main/java/seedu/jelphabot/logic/commands/DoneCommand.java
new file mode 100644
index 00000000000..0157140f81e
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/DoneCommand.java
@@ -0,0 +1,142 @@
+//@@author eedenong
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.jelphabot.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.time.LocalDateTime;
+import java.util.Set;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.summary.Summary;
+import seedu.jelphabot.model.tag.Tag;
+import seedu.jelphabot.model.task.DateTime;
+import seedu.jelphabot.model.task.Description;
+import seedu.jelphabot.model.task.ModuleCode;
+import seedu.jelphabot.model.task.Priority;
+import seedu.jelphabot.model.task.Status;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.TimeSpent;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Marks the specified as done by updating it's status to COMPLETE.
+ */
+public class DoneCommand extends Command {
+
+ public static final String COMMAND_WORD = "done";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Marks the task specified by the index number as completed.\n"
+ + "Parameters: INDEX (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_MARK_TASK_COMPLETE_SUCCESS = "Marked task as completed: %1$s";
+ public static final String MESSAGE_TASK_ALREADY_MARKED_COMPLETE = "The specified task has already "
+ + "been marked as complete!";
+ public static final String MESSAGE_STOP_TASK_FIRST = "Please stop timer for this task before marking it as done!";
+
+ private final Index index;
+
+ /**
+ * @param index of the task in the filtered task list to mark done
+ */
+ public DoneCommand(Index index) {
+ requireNonNull(index);
+ this.index = index;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ ViewTaskList lastShownList = model.getLastShownList();
+
+ if (index.getZeroBased() >= lastShownList.size() || index.getZeroBased() < 0) {
+ throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToMarkDone = lastShownList.get(index.getZeroBased());
+
+ if (taskToMarkDone.isBeingTimed()) {
+ throw new CommandException(MESSAGE_STOP_TASK_FIRST);
+ }
+
+ Task doneTask = createDoneTask(taskToMarkDone);
+
+ boolean isSameTask = taskToMarkDone.equals(doneTask);
+
+ if (isSameTask) {
+ throw new CommandException(MESSAGE_TASK_ALREADY_MARKED_COMPLETE);
+ }
+
+ model.setTask(taskToMarkDone, doneTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), true, false, false));
+ model.setSummary(new Summary(model.getFilteredTaskList()));
+ return new CommandResult(String.format(MESSAGE_MARK_TASK_COMPLETE_SUCCESS, doneTask));
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the updated COMPLETE status, and updated DoneTime.
+ * DoneTime is set according to the time that the task was marked done.
+ * Creation of the {@code Task} is done by copying all the details of the given {@code Task}
+ * and creating a new {@code Task} object.
+ * @param task Task object to get the relevant details from.
+ * @return Task object with it's status set as COMPLETE.
+ */
+ public static Task createDoneTask(Task task) {
+ Description description = task.getDescription();
+ ModuleCode moduleCode = task.getModuleCode();
+ Set tags = task.getTags();
+ DateTime dateTime = task.getDateTime();
+ Status status = Status.COMPLETE;
+ String doneTimeString = LocalDateTime.now().format(DateTime.STANDARD_FORMATTER);
+ LocalDateTime doneTime = LocalDateTime.parse(doneTimeString, DateTime.STANDARD_FORMATTER);
+ Priority priority = task.getPriority();
+ TimeSpent timeSpent = task.getTimeSpent();
+
+ return new Task(description, status, dateTime, doneTime, moduleCode, priority, tags, timeSpent);
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the updated COMPLETE status, and updated DoneTime.
+ * DoneTime is set according to the String representing the time the task was completed.
+ * Creation of the {@code Task} is done by copying all the details of the given {@code Task}
+ * and creating a new {@code Task} object.
+ * @param task Task object to get the relevant details from.
+ * @param doneTimeString String representing the time that the task was marked done.
+ * @return Task object with it's status set as COMPLETE and it's doneTime set as the doneTimeString.
+ */
+ protected static Task createDoneTask(Task task, String doneTimeString) {
+ Description description = task.getDescription();
+ ModuleCode moduleCode = task.getModuleCode();
+ Set tags = task.getTags();
+ DateTime dateTime = task.getDateTime();
+ Status status = Status.COMPLETE;
+ LocalDateTime doneTime = LocalDateTime.parse(doneTimeString);
+ Priority priority = task.getPriority();
+ TimeSpent timeSpent = task.getTimeSpent();
+
+ return new Task(description, status, dateTime, doneTime, moduleCode, priority, tags, timeSpent);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof DoneCommand)) {
+ return false;
+ }
+
+ // state check
+ DoneCommand d = (DoneCommand) other;
+ return index.equals(d.index);
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/EditCommand.java b/src/main/java/seedu/jelphabot/logic/commands/EditCommand.java
new file mode 100644
index 00000000000..2a840ac31a3
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/EditCommand.java
@@ -0,0 +1,237 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DATETIME;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_MODULE_CODE;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_TAG;
+import static seedu.jelphabot.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.commons.util.CollectionUtil;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.summary.Summary;
+import seedu.jelphabot.model.tag.Tag;
+import seedu.jelphabot.model.task.DateTime;
+import seedu.jelphabot.model.task.Description;
+import seedu.jelphabot.model.task.ModuleCode;
+import seedu.jelphabot.model.task.Priority;
+import seedu.jelphabot.model.task.Status;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.TimeSpent;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Edits the details of an existing task in the task list.
+ */
+public class EditCommand extends Command {
+
+ public static final String COMMAND_WORD = "edit";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the task identified "
+ + "by the index number used in the displayed task list. "
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters:\n"
+ + " " + "INDEX (must be a positive integer)\n"
+ + " " + "[" + PREFIX_DESCRIPTION + "DESCRIPTION]\n"
+ + " " + "[" + PREFIX_DATETIME + "DATETIME]\n"
+ + " " + "[" + PREFIX_MODULE_CODE + "MODULE_CODE]\n"
+ + " " + "[" + PREFIX_PRIORITY + "PRIORITY (-1, 0, or 1)]\n"
+ + " " + "[" + PREFIX_TAG + "TAG]...\n"
+ + "Example: " + COMMAND_WORD + " 1 " + PREFIX_MODULE_CODE + "CS2105 "
+ + PREFIX_DATETIME + "Jan-1-2020 20 20 "
+ + PREFIX_TAG + "Ungraded";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Edited Task: %1$s";
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+ public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task list.";
+ public static final String MESSAGE_CANNOT_EDIT_TASK = "This task cannot be edited while the timer is running.";
+
+ private final Index index;
+ private final EditTaskDescriptor editTaskDescriptor;
+
+ /**
+ * @param index of the task in the filtered task list to edit
+ * @param editTaskDescriptor details to edit the task with
+ */
+ public EditCommand(Index index, EditTaskDescriptor editTaskDescriptor) {
+ requireNonNull(index);
+ requireNonNull(editTaskDescriptor);
+
+ this.index = index;
+ this.editTaskDescriptor = new EditTaskDescriptor(editTaskDescriptor);
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ */
+ private static Task createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor) {
+ assert taskToEdit != null;
+
+ Description updatedDescription = editTaskDescriptor.getDescription().orElse(taskToEdit.getDescription());
+ ModuleCode updatedModuleCode = editTaskDescriptor.getModuleCode().orElse(taskToEdit.getModuleCode());
+ Set updatedTags = editTaskDescriptor.getTags().orElse(taskToEdit.getTags());
+ DateTime dateTime = editTaskDescriptor.getDateTime().orElse(taskToEdit.getDateTime());
+ Status updatedStatus = taskToEdit.getStatus();
+ Priority updatedPriority = editTaskDescriptor.getPriority().orElse(taskToEdit.getPriority());
+ TimeSpent timeSpent = taskToEdit.getTimeSpent();
+
+ return new Task(updatedDescription, updatedStatus, dateTime, updatedModuleCode, updatedPriority, updatedTags,
+ timeSpent
+ );
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ ViewTaskList lastShownList = model.getLastShownList();
+
+ if (index.getZeroBased() >= lastShownList.size() || index.getZeroBased() < 0) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToEdit = lastShownList.get(index.getZeroBased());
+ Task editedTask = createEditedTask(taskToEdit, editTaskDescriptor);
+
+ if (taskToEdit.isBeingTimed()) {
+ throw new CommandException(MESSAGE_CANNOT_EDIT_TASK);
+ } else if (!taskToEdit.isSameTask(editedTask) && model.hasTask(editedTask)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TASK);
+ }
+
+ model.setTask(taskToEdit, editedTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), true, false, false));
+ model.setSummary(new Summary(model.getFilteredTaskList()));
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, editedTask));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditCommand)) {
+ return false;
+ }
+
+ // state check
+ EditCommand e = (EditCommand) other;
+ return index.equals(e.index) && editTaskDescriptor.equals(e.editTaskDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the task with. Each non-empty field value will
+ * replace the corresponding field value of the task.
+ */
+ public static class EditTaskDescriptor {
+ private Description description;
+ private ModuleCode moduleCode;
+ private Set tags;
+ private DateTime dateTime;
+ private Priority priority;
+
+ public EditTaskDescriptor() {
+ }
+
+ /**
+ * Copy constructor. A defensive copy of {@code tags} is used internally.
+ */
+ public EditTaskDescriptor(EditTaskDescriptor toCopy) {
+ setDescription(toCopy.description);
+ setModuleCode(toCopy.moduleCode);
+ setTags(toCopy.tags);
+ setDateTime(toCopy.dateTime);
+ setPriority(toCopy.priority);
+ }
+
+ /**
+ * Returns true if at least one field is edited.
+ */
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(description, dateTime, moduleCode, tags, priority);
+ }
+
+ public Optional getDescription() {
+ return Optional.ofNullable(description);
+ }
+
+ public void setDescription(Description description) {
+ this.description = description;
+ }
+
+ public Optional getModuleCode() {
+ return Optional.ofNullable(moduleCode);
+ }
+
+ public void setModuleCode(ModuleCode moduleCode) {
+ this.moduleCode = moduleCode;
+ }
+
+ public Optional getPriority() {
+ return Optional.ofNullable(priority);
+ }
+
+ public void setPriority(Priority priority) {
+ this.priority = priority;
+ }
+
+ /**
+ * Sets {@code tags} to this object's {@code tags}. A defensive copy of
+ * {@code tags} is used internally.
+ */
+ public void setTags(Set tags) {
+ this.tags = (tags != null) ? new HashSet<>(tags) : null;
+ }
+
+ /**
+ * Returns an unmodifiable tag set, which throws
+ * {@code UnsupportedOperationException} if modification is attempted. Returns
+ * {@code Optional#empty()} if {@code tags} is null.
+ */
+ public Optional> getTags() {
+ return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
+ }
+
+ public void setDateTime(DateTime dateTime) {
+ this.dateTime = dateTime;
+ }
+
+ public Optional getDateTime() {
+ return Optional.ofNullable(dateTime);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditTaskDescriptor)) {
+ return false;
+ }
+
+ // state check
+ EditTaskDescriptor e = (EditTaskDescriptor) other;
+
+ return getDescription().equals(e.getDescription()) && getDateTime().equals(e.getDateTime())
+ && getModuleCode().equals(e.getModuleCode())
+ && getPriority().equals(e.getPriority()) && getTags().equals(e.getTags());
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ExitCommand.java
similarity index 53%
rename from src/main/java/seedu/address/logic/commands/ExitCommand.java
rename to src/main/java/seedu/jelphabot/logic/commands/ExitCommand.java
index 3dd85a8ba90..a339b78e543 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/jelphabot/logic/commands/ExitCommand.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.commands;
+package seedu.jelphabot.logic.commands;
-import seedu.address.model.Model;
+import seedu.jelphabot.model.Model;
/**
* Terminates the program.
@@ -9,7 +9,10 @@ public class ExitCommand extends Command {
public static final String COMMAND_WORD = "exit";
- public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ...";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Exits the program and closes the window.\n"
+ + "Example: " + COMMAND_WORD;
+
+ public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting JelphaBot as requested ...";
@Override
public CommandResult execute(Model model) {
diff --git a/src/main/java/seedu/jelphabot/logic/commands/FindCommand.java b/src/main/java/seedu/jelphabot/logic/commands/FindCommand.java
new file mode 100644
index 00000000000..bc744d4793d
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/FindCommand.java
@@ -0,0 +1,41 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.task.predicates.DescriptionContainsKeywordsPredicate;
+
+/**
+ * Finds and lists all tasks in task list whose task description contains any of the
+ * argument keywords. Keyword matching is case insensitive.
+ */
+public class FindCommand extends Command {
+
+ public static final String COMMAND_WORD = "find";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks whose names contain any of "
+ + "the specified keywords (case-insensitive) and displays them as a list.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " assignment";
+
+ private final DescriptionContainsKeywordsPredicate predicate;
+
+ public FindCommand(DescriptionContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(predicate);
+ return new CommandResult(
+ String.format(Messages.MESSAGE_TASKS_LISTED_OVERVIEW, model.getFilteredTaskList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindCommand // instanceof handles nulls
+ && predicate.equals(((FindCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/jelphabot/logic/commands/HelpCommand.java
similarity index 87%
rename from src/main/java/seedu/address/logic/commands/HelpCommand.java
rename to src/main/java/seedu/jelphabot/logic/commands/HelpCommand.java
index bf824f91bd0..69d67b1d7bb 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/jelphabot/logic/commands/HelpCommand.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.commands;
+package seedu.jelphabot.logic.commands;
-import seedu.address.model.Model;
+import seedu.jelphabot.model.Model;
/**
* Format full help instructions for every command for display.
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ListCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ListCommand.java
new file mode 100644
index 00000000000..dc4f418a3f7
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ListCommand.java
@@ -0,0 +1,58 @@
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import seedu.jelphabot.model.Model;
+
+/**
+ * Lists all tasks in the task list to the user.
+ *
+ * @@author yaojiethng
+ */
+public class ListCommand extends Command {
+
+ public static final String COMMAND_WORD = "list";
+ public static final String COMMAND_SHORTCUT = ":T";
+ public static final String COMMAND_SHORTCUT_TWO = ":t";
+
+
+ public static final String DATE_GROUPING = "date";
+ public static final String MODULE_GROUPING = "module";
+
+ public static final String MESSAGE_SUCCESS = "Listed all tasks by %s.";
+ public static final String MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT = "Switched to Task List panel";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Switches to Task List panel and lists all tasks.\n"
+ + "This command groups tasks by Date by default, but you can also "
+ + "group by module. "
+ + "Parameters:\n"
+ + " " + "[" + DATE_GROUPING + "]\n"
+ + " " + "[" + MODULE_GROUPING + "]\n"
+ + "Example: " + COMMAND_WORD + " module";
+
+ private final String grouping;
+
+ public ListCommand() {
+ this.grouping = "none";
+ }
+
+ public ListCommand(String grouping) {
+ this.grouping = grouping;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ switch (grouping) {
+ case "module":
+ return new CommandResult(String.format(MESSAGE_SUCCESS, grouping)).isShowModuleTaskList();
+ case "date":
+ return new CommandResult(String.format(MESSAGE_SUCCESS, grouping)).isShowDateTaskList();
+ case "none": // Fallthrough
+ default:
+ return new CommandResult(MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT).isShowDateTaskList();
+ }
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ProductivityCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ProductivityCommand.java
new file mode 100644
index 00000000000..dff52fe50a5
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ProductivityCommand.java
@@ -0,0 +1,25 @@
+// @@author Clouddoggo
+
+package seedu.jelphabot.logic.commands;
+
+import seedu.jelphabot.model.Model;
+
+/**
+ * Switches to the productivity panel.
+ */
+public class ProductivityCommand extends Command {
+
+ public static final String COMMAND_WORD = "productivity";
+ public static final String COMMAND_SHORTCUT_UPPER = ":P";
+ public static final String COMMAND_SHORTCUT_LOWER = ":p";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows productivity panel.\n"
+ + "Example: " + COMMAND_WORD;
+
+ public static final String MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT = "Switched to productivity panel.";
+
+ @Override
+ public CommandResult execute(Model model) {
+ return new CommandResult(MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT).isShowProductivity();
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ReminderCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ReminderCommand.java
new file mode 100644
index 00000000000..7b902523d33
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ReminderCommand.java
@@ -0,0 +1,74 @@
+//@@author yapdianhao
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_REMIND_DAY;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_REMIND_HOUR;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Displays to the user a list of tasks that will due in a week.
+ */
+public class ReminderCommand extends Command {
+
+ public static final String MESSAGE_DUPLICATE_REMINDER = "This task already has a reminder!"
+ + " Please delete the current reminder with delrem "
+ + "[INDEX] first!";
+ public static final String MESSAGE_TASK_ALREADY_MARKED_COMPLETE = "The specified task has already "
+ + "been marked as complete!";
+ public static final String MESSAGE_SUCCESS = "Added reminder for task %d!";
+ public static final String COMMAND_WORD = "reminder";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Marks a reminder on the given task "
+ + " on the specified date. "
+ + "Parameters:\n" + "INDEX (must be a positive integer) "
+ + " " + "[" + PREFIX_REMIND_DAY
+ + "DAYS TO REMIND (between 0 and 7)]\n"
+ + " " + "[" + PREFIX_REMIND_HOUR
+ + "HOURS TO REMIND (between 0 and 24)]\n";
+ public static final String MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT = "Switched to reminder panel.";
+
+ private final Reminder reminder;
+ private final Index index;
+
+ public ReminderCommand(Index index, Reminder reminder) {
+ requireAllNonNull(index, reminder);
+ this.index = index;
+ this.reminder = reminder;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ ViewTaskList lastShownList = model.getLastShownList();
+ if (model.hasReminder(reminder)) {
+ //model.setReminder(reminder, reminder);
+ throw new CommandException(MESSAGE_DUPLICATE_REMINDER);
+ }
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ Task taskMarkedWithReminder = lastShownList.get(index.getZeroBased());
+ String taskMarkedWithReminderDoneTimeString = taskMarkedWithReminder.getDoneTime().toString();
+ Task taskToCompare = DoneCommand.createDoneTask(taskMarkedWithReminder, taskMarkedWithReminderDoneTimeString);
+ if (taskMarkedWithReminder.equals(taskToCompare)) {
+ throw new CommandException(MESSAGE_TASK_ALREADY_MARKED_COMPLETE);
+ }
+ model.addReminder(reminder);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, reminder.getIndex().getOneBased()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof ReminderCommand // instanceof handles nulls
+ && index.equals(((ReminderCommand) other).index)); // state check
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ReminderTabCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ReminderTabCommand.java
new file mode 100644
index 00000000000..1fa09ed0a71
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ReminderTabCommand.java
@@ -0,0 +1,24 @@
+//@@author yapdianhao
+package seedu.jelphabot.logic.commands;
+
+import seedu.jelphabot.model.Model;
+
+/**
+ * Switches to the Reminder panel.
+ */
+public class ReminderTabCommand extends Command {
+
+ public static final String COMMAND_WORD = "remindertab";
+ public static final String COMMAND_WORD_UPPER = ":R";
+ public static final String COMMAND_WORD_LOWER = ":r";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows reminder panel.\n"
+ + "Example: " + COMMAND_WORD;
+
+ public static final String MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT = "Switched to reminder panel.";
+
+ @Override
+ public CommandResult execute(Model model) {
+ return new CommandResult(MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT).isShowReminder();
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ShowCompletedCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ShowCompletedCommand.java
new file mode 100644
index 00000000000..0bc26ee2a90
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ShowCompletedCommand.java
@@ -0,0 +1,34 @@
+//@@author eedenong
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.function.Predicate;
+
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.predicates.TaskIsCompletedPredicate;
+
+/**
+ * Displays to the user a list of tasks that are currently of the COMPLETE status.
+ */
+public class ShowCompletedCommand extends Command {
+ public static final String COMMAND_WORD = "show-completed";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows all completed tasks in the task list";
+
+ public static final String MESSAGE_SUCCESS = "Displaying all completed tasks";
+
+ public static final Predicate COMPLETED_PREDICATE = new TaskIsCompletedPredicate();
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(COMPLETED_PREDICATE);
+ StringBuilder sb = new StringBuilder(MESSAGE_SUCCESS);
+ if (model.getFilteredTaskList().size() == 0) {
+ sb.append("\nYou do not have any tasks that are complete!");
+ }
+ return new CommandResult(sb.toString()).isShowDateTaskList();
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/ShowIncompleteCommand.java b/src/main/java/seedu/jelphabot/logic/commands/ShowIncompleteCommand.java
new file mode 100644
index 00000000000..4a13711526c
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/ShowIncompleteCommand.java
@@ -0,0 +1,35 @@
+//@@author eedenong
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.function.Predicate;
+
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.predicates.TaskIsIncompletePredicate;
+
+/**
+ * Displays to the user a list of tasks that are currently of the INCOMPLETE status.
+ */
+public class ShowIncompleteCommand extends Command {
+
+ public static final String COMMAND_WORD = "show-incomplete";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows all incomplete tasks in the task list";
+
+ public static final String MESSAGE_SUCCESS = "Displaying all incomplete tasks";
+
+ public static final Predicate INCOMPLETE_PREDICATE = new TaskIsIncompletePredicate();
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(INCOMPLETE_PREDICATE);
+ StringBuilder sb = new StringBuilder(MESSAGE_SUCCESS);
+ if (model.getFilteredTaskList().size() == 0) {
+ sb.append("\nYou do not have any tasks that are incomplete!");
+ }
+ return new CommandResult(sb.toString()).isShowDateTaskList();
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/StartTimerCommand.java b/src/main/java/seedu/jelphabot/logic/commands/StartTimerCommand.java
new file mode 100644
index 00000000000..8b57f8dd246
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/StartTimerCommand.java
@@ -0,0 +1,78 @@
+//@@author Clouddoggo
+
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.task.Status;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Starts a timer for a task.
+ */
+public class StartTimerCommand extends Command {
+ public static final String COMMAND_WORD = "start";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Starts the timer for the task specified by the index number.\n"
+ + "Parameters: INDEX (must be a positive integer)\n" + "Example: "
+ + COMMAND_WORD + " 1";
+ public static final String MESSAGE_SUCCESS = "Started timer for task %d. %s %s.";
+ public static final String MESSAGE_TASK_ALREADY_TIMED = "This task has already been marked as done and cannot be "
+ + "timed.";
+ public static final String MESSAGE_TIMER_ALREADY_STARTED = "Timer for this task has already been started.";
+
+ private Index targetIndex;
+
+ public StartTimerCommand(Index targetIndex) {
+ requireNonNull(targetIndex);
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ ViewTaskList lastShownList = model.getLastShownList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToTime = lastShownList.get(targetIndex.getZeroBased());
+
+ if (taskToTime.getStatus() == Status.COMPLETE) {
+ throw new CommandException(MESSAGE_TASK_ALREADY_TIMED);
+ } else if (taskToTime.isBeingTimed()) {
+ throw new CommandException(MESSAGE_TIMER_ALREADY_STARTED);
+ }
+
+ taskToTime.startTimer();
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), false, true, false));
+ return new CommandResult(String.format(MESSAGE_SUCCESS, targetIndex.getOneBased(),
+ taskToTime.getModuleCode().toString(), taskToTime.getDescription().toString()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof StartTimerCommand)) {
+ return false;
+ }
+
+ // state check
+ StartTimerCommand d = (StartTimerCommand) other;
+ return targetIndex.equals(d.targetIndex);
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/StopTimerCommand.java b/src/main/java/seedu/jelphabot/logic/commands/StopTimerCommand.java
new file mode 100644
index 00000000000..216368940a4
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/StopTimerCommand.java
@@ -0,0 +1,76 @@
+//@@author Clouddoggo
+
+package seedu.jelphabot.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.exceptions.CommandException;
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Starts a timer for a task.
+ */
+public class StopTimerCommand extends Command {
+ public static final String COMMAND_WORD = "stop";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Stops the timer for the task specified by the index number.\n"
+ + "Parameters: INDEX (must be a positive integer)\n" + "Example: "
+ + COMMAND_WORD + " 1";
+ public static final String MESSAGE_SUCCESS = "Stopped timer for task %d. %s %s.\n"
+ + "Total time spent on this task: %s.";
+ public static final String MESSAGE_NO_TIMER_TO_STOP = "No timers were started.";
+
+ private Index targetIndex;
+
+ public StopTimerCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ ViewTaskList lastShownList = model.getLastShownList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToStop = lastShownList.get(targetIndex.getZeroBased());
+ Task dummy = taskToStop;
+
+ if (!taskToStop.isBeingTimed()) {
+ throw new CommandException(MESSAGE_NO_TIMER_TO_STOP);
+ }
+
+ taskToStop.stopTimer();
+ model.setTask(dummy, taskToStop);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ model.setProductivity(new Productivity(model.getFilteredTaskList(), false, false, true));
+ return new CommandResult(String.format(MESSAGE_SUCCESS, targetIndex.getOneBased(),
+ taskToStop.getModuleCode().toString(), taskToStop.getDescription().toString(),
+ taskToStop.getTimeSpent().toString()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof StopTimerCommand)) {
+ return false;
+ }
+
+ // state check
+ StopTimerCommand d = (StopTimerCommand) other;
+ return targetIndex.equals(d.targetIndex);
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/commands/SummaryCommand.java b/src/main/java/seedu/jelphabot/logic/commands/SummaryCommand.java
new file mode 100644
index 00000000000..6e0a21170ee
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/commands/SummaryCommand.java
@@ -0,0 +1,24 @@
+//@@author eedenong
+package seedu.jelphabot.logic.commands;
+
+import seedu.jelphabot.model.Model;
+import seedu.jelphabot.model.summary.Summary;
+
+/**
+ * Switches to the summary panel.
+ */
+public class SummaryCommand extends Command {
+
+ public static final String COMMAND_WORD = "summary";
+ public static final String COMMAND_SHORTCUT_UPPER = ":S";
+ public static final String COMMAND_SHORTCUT_LOWER = ":s";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows summary panel.\n" + "Example: " + COMMAND_WORD;
+ public static final String MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT = "Switched to summary panel";
+
+ @Override
+ public CommandResult execute(Model model) {
+ model.setSummary(new Summary(model.getFilteredTaskList()));
+ return new CommandResult(MESSAGE_SWITCH_PANEL_ACKNOWLEDGEMENT, false, false).isShowSummary();
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/jelphabot/logic/commands/exceptions/CommandException.java
similarity index 81%
rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
rename to src/main/java/seedu/jelphabot/logic/commands/exceptions/CommandException.java
index a16bd14f2cd..0aff68b08b0 100644
--- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
+++ b/src/main/java/seedu/jelphabot/logic/commands/exceptions/CommandException.java
@@ -1,4 +1,6 @@
-package seedu.address.logic.commands.exceptions;
+package seedu.jelphabot.logic.commands.exceptions;
+
+import seedu.jelphabot.logic.commands.Command;
/**
* Represents an error which occurs during execution of a {@link Command}.
diff --git a/src/main/java/seedu/jelphabot/logic/parser/AddCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/AddCommandParser.java
new file mode 100644
index 00000000000..f4c650b751e
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/AddCommandParser.java
@@ -0,0 +1,77 @@
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DATETIME;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_MODULE_CODE;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.time.Duration;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import seedu.jelphabot.logic.commands.AddCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.tag.Tag;
+import seedu.jelphabot.model.task.DateTime;
+import seedu.jelphabot.model.task.Description;
+import seedu.jelphabot.model.task.ModuleCode;
+import seedu.jelphabot.model.task.Priority;
+import seedu.jelphabot.model.task.Status;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.TimeSpent;
+
+/**
+ * Parses input arguments and creates a new AddCommand object
+ */
+public class AddCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddCommand
+ * and returns an AddCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(
+ args,
+ PREFIX_DESCRIPTION,
+ PREFIX_MODULE_CODE,
+ PREFIX_PRIORITY,
+ PREFIX_DATETIME,
+ PREFIX_TAG
+ );
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_DESCRIPTION, PREFIX_MODULE_CODE, PREFIX_DATETIME)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+
+ //noinspection OptionalGetWithoutIsPresent guaranteed present return from ParserUtil
+ Description description = ParserUtil.parseDescription(argMultimap.getValue(PREFIX_DESCRIPTION).get());
+ //noinspection OptionalGetWithoutIsPresent guaranteed present return from ParserUtil
+ DateTime dateTime = ParserUtil.parseDateTime(argMultimap.getValue(PREFIX_DATETIME).get());
+ //noinspection OptionalGetWithoutIsPresent guaranteed present return from ParserUtil
+ ModuleCode moduleCode = ParserUtil.parseModuleCode(argMultimap.getValue(PREFIX_MODULE_CODE).get());
+ Priority priority = Priority.MEDIUM;
+ if (argMultimap.getValue(PREFIX_PRIORITY).isPresent()) {
+ priority = ParserUtil.parsePriority(argMultimap.getValue(PREFIX_PRIORITY).get());
+ }
+ Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
+
+ Task task = new Task(description, Status.INCOMPLETE, dateTime, moduleCode, priority, tagList,
+ new TimeSpent(Duration.ZERO));
+
+ return new AddCommand(task);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/seedu/jelphabot/logic/parser/ArgumentMultimap.java
similarity index 98%
rename from src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
rename to src/main/java/seedu/jelphabot/logic/parser/ArgumentMultimap.java
index 954c8e18f8e..c770ab8d9a0 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/ArgumentMultimap.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.jelphabot.logic.parser;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/seedu/jelphabot/logic/parser/ArgumentTokenizer.java
similarity index 99%
rename from src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
rename to src/main/java/seedu/jelphabot/logic/parser/ArgumentTokenizer.java
index 5c9aebfa488..756a6d8c160 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/ArgumentTokenizer.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.jelphabot.logic.parser;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/main/java/seedu/jelphabot/logic/parser/CalendarCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/CalendarCommandParser.java
new file mode 100644
index 00000000000..bd4344b6705
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/CalendarCommandParser.java
@@ -0,0 +1,105 @@
+package seedu.jelphabot.logic.parser;
+
+import java.time.LocalDate;
+import java.time.YearMonth;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+
+import seedu.jelphabot.commons.core.Messages;
+import seedu.jelphabot.commons.util.DateUtil;
+import seedu.jelphabot.logic.commands.CalendarCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.task.predicates.TaskDueWithinDayPredicate;
+
+//@@author alam8064
+/**
+ * Parses input argument and creates a new CalendarCommand object
+ */
+public class CalendarCommandParser implements Parser {
+
+ private static final DateTimeFormatter ACCEPTED_DATE_FORMATS =
+ new DateTimeFormatterBuilder()
+ .appendOptional(DateTimeFormatter.ofPattern("MMM-d-uuuu"))
+ .appendOptional(DateTimeFormatter.ofPattern("MMM/d/uuuu"))
+ .appendOptional(DateTimeFormatter.ofPattern("d-MMM-uuuu"))
+ .appendOptional(DateTimeFormatter.ofPattern("d/MMM/uuuu"))
+ .toFormatter().withResolverStyle(ResolverStyle.STRICT);
+
+ private static final DateTimeFormatter ACCEPTED_YEARMONTH_FORMATS =
+ new DateTimeFormatterBuilder()
+ .appendOptional(DateTimeFormatter.ofPattern("MMM-uuuu"))
+ .appendOptional(DateTimeFormatter.ofPattern("MMM/uuuu"))
+ .appendOptional(DateTimeFormatter.ofPattern("uuuu/MMM"))
+ .appendOptional(DateTimeFormatter.ofPattern("uuuu-MMM"))
+ .appendOptional(DateTimeFormatter.ofPattern("uuuu-MM"))
+ .appendOptional(DateTimeFormatter.ofPattern("uuuu/MM"))
+ .appendOptional(DateTimeFormatter.ofPattern("uu-MM"))
+ .appendOptional(DateTimeFormatter.ofPattern("uu/MM"))
+ .toFormatter().withResolverStyle(ResolverStyle.STRICT);
+
+ /**
+ * Parses the given {@code String} of argument in the context of the CalendarCommand
+ * and returns a CalendarCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public CalendarCommand parse(String args) throws ParseException {
+ String input = args.trim();
+ if (input.isEmpty()) {
+ // throw new ParseException(
+ // String.format(MESSAGE_INVALID_COMMAND_FORMAT, CalendarCommand.MESSAGE_USAGE));
+ return new CalendarCommand();
+ } else if (input.length() > 8) {
+ //case for switching date for task list
+ if (!isValidDate(input)) {
+ throw new ParseException(Messages.MESSAGE_INVALID_DATE_FORMAT);
+ }
+ LocalDate date = LocalDate.parse(input, ACCEPTED_DATE_FORMATS);
+ return new CalendarCommand(new TaskDueWithinDayPredicate(date));
+ } else if (input.equals("today")) {
+ YearMonth yearMonth = YearMonth.now();
+ return new CalendarCommand(new TaskDueWithinDayPredicate(DateUtil.getDateToday()), true);
+ } else {
+ //case for switching month view
+ if (!isValidYearMonth(input)) {
+ throw new ParseException(Messages.MESSAGE_INVALID_YEARMONTH_FORMAT);
+ }
+ YearMonth yearMonth = YearMonth.parse(input, ACCEPTED_YEARMONTH_FORMATS);
+ return new CalendarCommand(yearMonth);
+ }
+ }
+
+ /**
+ * Returns if the given string is a valid date format, specified in
+ * the ACCEPTED_DATE_FORMATS DateTimeFormatter.
+ *
+ * @param test The date to be checked.
+ * @return The boolean representing whether the date provided is valid.
+ */
+ public static boolean isValidDate(String test) {
+ try {
+ LocalDate.parse(test, ACCEPTED_DATE_FORMATS);
+ return true;
+ } catch (DateTimeParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns if the given string is a valid date format, specified in
+ * the ACCEPTED_YEARMONTH_FORMATS DateTimeFormatter.
+ *
+ * @param test The date of yearmonth to be checked.
+ * @return The boolean representing whether the date provided is valid.
+ */
+ public static boolean isValidYearMonth(String test) {
+ try {
+ YearMonth.parse(test, ACCEPTED_YEARMONTH_FORMATS);
+ return true;
+ } catch (DateTimeParseException e) {
+ return false;
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/CliSyntax.java b/src/main/java/seedu/jelphabot/logic/parser/CliSyntax.java
new file mode 100644
index 00000000000..dd47674490e
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/CliSyntax.java
@@ -0,0 +1,17 @@
+package seedu.jelphabot.logic.parser;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
+ */
+public class CliSyntax {
+
+ /* Prefix definitions */
+ public static final Prefix PREFIX_DESCRIPTION = new Prefix("d/");
+ public static final Prefix PREFIX_DATETIME = new Prefix("dt/");
+ public static final Prefix PREFIX_MODULE_CODE = new Prefix("m/");
+ public static final Prefix PREFIX_PRIORITY = new Prefix("p/");
+ public static final Prefix PREFIX_TAG = new Prefix("t/");
+ public static final Prefix PREFIX_REMIND_DAY = new Prefix("days/");
+ public static final Prefix PREFIX_REMIND_HOUR = new Prefix("hours/");
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/DeleteCommandParser.java
similarity index 71%
rename from src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
rename to src/main/java/seedu/jelphabot/logic/parser/DeleteCommandParser.java
index 522b93081cc..d680cf2237a 100644
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/DeleteCommandParser.java
@@ -1,10 +1,11 @@
-package seedu.address.logic.parser;
+//@@author yapdianhao
+package seedu.jelphabot.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.DeleteCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
/**
* Parses input arguments and creates a new DeleteCommand object
diff --git a/src/main/java/seedu/jelphabot/logic/parser/DeleteReminderCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/DeleteReminderCommandParser.java
new file mode 100644
index 00000000000..f3aafa74010
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/DeleteReminderCommandParser.java
@@ -0,0 +1,29 @@
+//@@author yapdianhao
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.DeleteReminderCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DeleteCommand object
+ */
+public class DeleteReminderCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the DeleteCommand
+ * and returns a DeleteCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeleteReminderCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new DeleteReminderCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteReminderCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/DoneCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/DoneCommandParser.java
new file mode 100644
index 00000000000..c368b2ddd1a
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/DoneCommandParser.java
@@ -0,0 +1,32 @@
+//@@author eedenong
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.DoneCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DoneCommand object
+ */
+public class DoneCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of DoneCommand
+ * and returns a DoneCommand object for execution.
+ * @param args user arguments.
+ * @return a DoneCommand object to be used for execution.
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ public DoneCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new DoneCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DoneCommand.MESSAGE_USAGE), pe);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/EditCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/EditCommandParser.java
new file mode 100644
index 00000000000..fc726913cae
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/EditCommandParser.java
@@ -0,0 +1,92 @@
+package seedu.jelphabot.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DATETIME;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_MODULE_CODE;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.EditCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.tag.Tag;
+
+/**
+ * Parses input arguments and creates a new EditCommand object
+ */
+public class EditCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditCommand
+ * and returns an EditCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EditCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(
+ args,
+ PREFIX_DESCRIPTION,
+ PREFIX_DATETIME,
+ PREFIX_MODULE_CODE,
+ PREFIX_PRIORITY,
+ PREFIX_TAG
+ );
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditCommand.EditTaskDescriptor editTaskDescriptor = new EditCommand.EditTaskDescriptor();
+ if (argMultimap.getValue(PREFIX_DESCRIPTION).isPresent()) {
+ editTaskDescriptor.setDescription(
+ ParserUtil.parseDescription(argMultimap.getValue(PREFIX_DESCRIPTION).get()));
+ }
+ if (argMultimap.getValue(PREFIX_DATETIME).isPresent()) {
+ editTaskDescriptor.setDateTime(
+ ParserUtil.parseDateTime(argMultimap.getValue(PREFIX_DATETIME).get()));
+ }
+ if (argMultimap.getValue(PREFIX_MODULE_CODE).isPresent()) {
+ editTaskDescriptor.setModuleCode(ParserUtil
+ .parseModuleCode(argMultimap.getValue(PREFIX_MODULE_CODE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_PRIORITY).isPresent()) {
+ editTaskDescriptor.setPriority(ParserUtil
+ .parsePriority(argMultimap.getValue(PREFIX_PRIORITY).get()));
+ }
+ parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editTaskDescriptor::setTags);
+
+ if (!editTaskDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
+ }
+ return new EditCommand(index, editTaskDescriptor);
+ }
+
+ /**
+ * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
+ * If {@code tags} contain only one element which is an empty string, it will be parsed into a
+ * {@code Set} containing zero tags.
+ */
+ private Optional> parseTagsForEdit(Collection tags) throws ParseException {
+ assert tags != null;
+
+ if (tags.isEmpty()) {
+ return Optional.empty();
+ }
+ Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
+ return Optional.of(ParserUtil.parseTags(tagSet));
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/FindCommandParser.java
similarity index 64%
rename from src/main/java/seedu/address/logic/parser/FindCommandParser.java
rename to src/main/java/seedu/jelphabot/logic/parser/FindCommandParser.java
index 4fb71f23103..d28820622f3 100644
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/FindCommandParser.java
@@ -1,12 +1,12 @@
-package seedu.address.logic.parser;
+package seedu.jelphabot.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import java.util.Arrays;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.jelphabot.logic.commands.FindCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.task.predicates.DescriptionContainsKeywordsPredicate;
/**
* Parses input arguments and creates a new FindCommand object
@@ -27,7 +27,7 @@ public FindCommand parse(String args) throws ParseException {
String[] nameKeywords = trimmedArgs.split("\\s+");
- return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
+ return new FindCommand(new DescriptionContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
}
}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/JelphaBotParser.java b/src/main/java/seedu/jelphabot/logic/parser/JelphaBotParser.java
new file mode 100644
index 00000000000..3bbf670d339
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/JelphaBotParser.java
@@ -0,0 +1,136 @@
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.jelphabot.logic.commands.AddCommand;
+import seedu.jelphabot.logic.commands.CalendarCommand;
+import seedu.jelphabot.logic.commands.ClearCommand;
+import seedu.jelphabot.logic.commands.Command;
+import seedu.jelphabot.logic.commands.DeleteCommand;
+import seedu.jelphabot.logic.commands.DeleteReminderCommand;
+import seedu.jelphabot.logic.commands.DoneCommand;
+import seedu.jelphabot.logic.commands.EditCommand;
+import seedu.jelphabot.logic.commands.ExitCommand;
+import seedu.jelphabot.logic.commands.FindCommand;
+import seedu.jelphabot.logic.commands.HelpCommand;
+import seedu.jelphabot.logic.commands.ListCommand;
+import seedu.jelphabot.logic.commands.ProductivityCommand;
+import seedu.jelphabot.logic.commands.ReminderCommand;
+import seedu.jelphabot.logic.commands.ReminderTabCommand;
+import seedu.jelphabot.logic.commands.ShowCompletedCommand;
+import seedu.jelphabot.logic.commands.ShowIncompleteCommand;
+import seedu.jelphabot.logic.commands.StartTimerCommand;
+import seedu.jelphabot.logic.commands.StopTimerCommand;
+import seedu.jelphabot.logic.commands.SummaryCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses user input.
+ */
+public class JelphaBotParser {
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput full user input string
+ * @return the command based on the user input
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public Command parseCommand(String userInput) throws ParseException {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
+ }
+ final String commandWord = matcher.group("commandWord");
+ final String arguments = matcher.group("arguments");
+ switch (commandWord) {
+
+ case AddCommand.COMMAND_WORD:
+ return new AddCommandParser().parse(arguments);
+
+ case EditCommand.COMMAND_WORD:
+ return new EditCommandParser().parse(arguments);
+
+ case DeleteCommand.COMMAND_WORD:
+ return new DeleteCommandParser().parse(arguments);
+
+ case DeleteReminderCommand.COMMAND_WORD:
+ return new DeleteReminderCommandParser().parse(arguments);
+
+ case ClearCommand.COMMAND_WORD:
+ return getCommand(arguments, new ClearCommand(), ClearCommand.MESSAGE_USAGE);
+
+ case FindCommand.COMMAND_WORD:
+ return new FindCommandParser().parse(arguments);
+
+ case ListCommand.COMMAND_WORD: // fallthrough
+ case ListCommand.COMMAND_SHORTCUT: // fallthrough
+ case ListCommand.COMMAND_SHORTCUT_TWO:
+ return new ListCommandParser().parse(arguments);
+
+ case ExitCommand.COMMAND_WORD:
+ return getCommand(arguments, new ExitCommand(), ExitCommand.MESSAGE_USAGE);
+
+ case HelpCommand.COMMAND_WORD:
+ return getCommand(arguments, new HelpCommand(), HelpCommand.MESSAGE_USAGE);
+
+ case ReminderCommand.COMMAND_WORD:
+ return new ReminderCommandParser().parse(arguments);
+
+ case ReminderTabCommand.COMMAND_WORD: // fallthrough
+ case ReminderTabCommand.COMMAND_WORD_UPPER: // fallthrough
+ case ReminderTabCommand.COMMAND_WORD_LOWER:
+ return getCommand(arguments, new ReminderTabCommand(), ReminderTabCommand.MESSAGE_USAGE);
+
+ case ShowCompletedCommand.COMMAND_WORD:
+ return getCommand(arguments, new ShowCompletedCommand(), ShowCompletedCommand.MESSAGE_USAGE);
+
+ case ShowIncompleteCommand.COMMAND_WORD:
+ return getCommand(arguments, new ShowIncompleteCommand(), ShowIncompleteCommand.MESSAGE_USAGE);
+
+ case DoneCommand.COMMAND_WORD:
+ return new DoneCommandParser().parse(arguments);
+
+ case CalendarCommand.COMMAND_WORD: // fallthrough
+ case CalendarCommand.COMMAND_SHORTCUT_UPPER: // fallthrough
+ case CalendarCommand.COMMAND_SHORTCUT_LOWER:
+ return new CalendarCommandParser().parse(arguments);
+
+ case SummaryCommand.COMMAND_WORD: // fallthrough
+ case SummaryCommand.COMMAND_SHORTCUT_UPPER: // fallthrough
+ case SummaryCommand.COMMAND_SHORTCUT_LOWER:
+ return getCommand(arguments, new SummaryCommand(), SummaryCommand.MESSAGE_USAGE);
+
+ case ProductivityCommand.COMMAND_WORD: // fallthrough
+ case ProductivityCommand.COMMAND_SHORTCUT_UPPER: // fallthrough
+ case ProductivityCommand.COMMAND_SHORTCUT_LOWER:
+ return getCommand(arguments, new ProductivityCommand(), ProductivityCommand.MESSAGE_USAGE);
+
+ case StartTimerCommand.COMMAND_WORD:
+ return new StartTimerCommandParser().parse(arguments);
+
+ case StopTimerCommand.COMMAND_WORD:
+ return new StopTimerCommandParser().parse(arguments);
+
+ default:
+ throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
+ }
+ }
+
+ private static Command getCommand(String arguments, Command command, String message) throws ParseException {
+ if (arguments.length() > 0) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, message));
+ }
+ return command;
+ }
+
+}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/ListCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/ListCommandParser.java
new file mode 100644
index 00000000000..0bb6c99352a
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/ListCommandParser.java
@@ -0,0 +1,29 @@
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.jelphabot.logic.commands.ListCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input argument and creates a new ListCommand object
+ */
+public class ListCommandParser implements Parser {
+
+ @Override
+ public ListCommand parse(String args) throws ParseException {
+ String input = args.trim();
+ if (input.isEmpty()) {
+ return new ListCommand();
+ }
+ switch (input) {
+ case ListCommand.DATE_GROUPING:
+ return new ListCommand("date");
+ case ListCommand.MODULE_GROUPING:
+ return new ListCommand("module");
+ default:
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/jelphabot/logic/parser/Parser.java
similarity index 71%
rename from src/main/java/seedu/address/logic/parser/Parser.java
rename to src/main/java/seedu/jelphabot/logic/parser/Parser.java
index d6551ad8e3f..d3ffc6e931b 100644
--- a/src/main/java/seedu/address/logic/parser/Parser.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/Parser.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.parser;
+package seedu.jelphabot.logic.parser;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.logic.commands.Command;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
/**
* Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}.
diff --git a/src/main/java/seedu/jelphabot/logic/parser/ParserUtil.java b/src/main/java/seedu/jelphabot/logic/parser/ParserUtil.java
new file mode 100644
index 00000000000..fb459dbf0e0
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/ParserUtil.java
@@ -0,0 +1,159 @@
+package seedu.jelphabot.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.commons.util.StringUtil;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.reminder.ReminderDay;
+import seedu.jelphabot.model.reminder.ReminderHour;
+import seedu.jelphabot.model.tag.Tag;
+import seedu.jelphabot.model.task.DateTime;
+import seedu.jelphabot.model.task.Description;
+import seedu.jelphabot.model.task.ModuleCode;
+import seedu.jelphabot.model.task.Priority;
+
+/**
+ * Contains utility methods used for parsing strings in the various *Parser classes.
+ */
+public class ParserUtil {
+
+ public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
+
+ /**
+ * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
+ * trimmed.
+ * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
+ */
+ public static Index parseIndex(String oneBasedIndex) throws ParseException {
+ String trimmedIndex = oneBasedIndex.trim();
+ if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
+ throw new ParseException(MESSAGE_INVALID_INDEX);
+ }
+ return Index.fromOneBased(Integer.parseInt(trimmedIndex));
+ }
+
+ /**
+ * Parses a {@code String name} into a {@code Description}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code name} is invalid.
+ */
+ public static Description parseDescription(String description) throws ParseException {
+ requireNonNull(description);
+ String trimmedDescription = description.trim();
+ if (!Description.isValidDescription(trimmedDescription)) {
+ throw new ParseException(Description.MESSAGE_CONSTRAINTS);
+ }
+ return new Description(trimmedDescription);
+ }
+
+ /**
+ * Parses a {@code String dateTime} into an {@code dateTime}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code dateTime} is invalid.
+ */
+ public static DateTime parseDateTime(String dateTime) throws ParseException {
+ requireNonNull(dateTime);
+ String trimmedDatetime = dateTime.trim();
+ if (!DateTime.isValidDateTime(trimmedDatetime)) {
+ throw new ParseException(DateTime.MESSAGE_CONSTRAINTS);
+ }
+ return new DateTime(trimmedDatetime);
+ }
+
+ /**
+ * Parses a {@code String module code} into an {@code ModuleCode}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code module code} is invalid.
+ */
+ public static ModuleCode parseModuleCode(String moduleCode) throws ParseException {
+ requireNonNull(moduleCode);
+ String trimmedModuleCode = moduleCode.trim();
+ if (!ModuleCode.isValidModuleCode(trimmedModuleCode)) {
+ throw new ParseException(ModuleCode.MESSAGE_CONSTRAINTS);
+ }
+ return new ModuleCode(trimmedModuleCode);
+ }
+
+ /**
+ * Parses a {@code String priority} into an {@code Priority}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code priority} is invalid.
+ */
+ public static Priority parsePriority(String priority) throws ParseException {
+ requireNonNull(priority);
+ String trimmedPriority = priority.trim();
+ if (!Priority.isValidPriority(trimmedPriority)) {
+ throw new ParseException(Priority.MESSAGE_CONSTRAINTS);
+ }
+ return Priority.toPriority(trimmedPriority);
+ }
+
+ /**
+ * Parses a {@code String tag} into a {@code Tag}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code tag} is invalid.
+ */
+ public static Tag parseTag(String tag) throws ParseException {
+ requireNonNull(tag);
+ String trimmedTag = tag.trim();
+ if (!Tag.isValidTagName(trimmedTag)) {
+ throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
+ }
+ return new Tag(trimmedTag);
+ }
+
+ /**
+ * Parses a {@code String reminderDay} into a {@code ReminderDay}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code reminderDay} is invalid.
+ */
+ public static ReminderDay parseReminderDay(String reminderDay) throws ParseException {
+ requireNonNull(reminderDay);
+ String trimmedReminderDay = reminderDay.trim();
+ //int convertedReminderDay = Integer.parseInt(trimmedReminderDay);
+ if (!ReminderDay.isValidReminderDay(trimmedReminderDay)) {
+ throw new ParseException(ReminderDay.MESSAGE_CONSTRAINTS);
+ }
+ //int convertedReminderDay = Integer.parseInt(trimmedReminderDay);
+ return new ReminderDay(trimmedReminderDay);
+ }
+
+ /**
+ * Parses a {@code String reminderHour} into a {@code ReminderHour}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code reminderHour} is invalid.
+ */
+ public static ReminderHour parseReminderHour(String reminderHour) throws ParseException {
+ requireNonNull(reminderHour);
+ String trimmedReminderHour = reminderHour.trim();
+ //int convertedReminderHour = Integer.parseInt(trimmedReminderHour);
+ if (!ReminderHour.isValidReminderHour(trimmedReminderHour)) {
+ throw new ParseException(ReminderHour.MESSAGE_CONSTRAINTS);
+ }
+ return new ReminderHour(trimmedReminderHour);
+ }
+
+ /**
+ * Parses {@code Collection tags} into a {@code Set}.
+ */
+ public static Set parseTags(Collection tags) throws ParseException {
+ requireNonNull(tags);
+ final Set tagSet = new HashSet<>();
+ for (String tagName : tags) {
+ tagSet.add(parseTag(tagName));
+ }
+ return tagSet;
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/Prefix.java b/src/main/java/seedu/jelphabot/logic/parser/Prefix.java
similarity index 95%
rename from src/main/java/seedu/address/logic/parser/Prefix.java
rename to src/main/java/seedu/jelphabot/logic/parser/Prefix.java
index c859d5fa5db..c598b56c8d5 100644
--- a/src/main/java/seedu/address/logic/parser/Prefix.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/Prefix.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.jelphabot.logic.parser;
/**
* A prefix that marks the beginning of an argument in an arguments string.
diff --git a/src/main/java/seedu/jelphabot/logic/parser/ReminderCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/ReminderCommandParser.java
new file mode 100644
index 00000000000..5c59bdeb236
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/ReminderCommandParser.java
@@ -0,0 +1,61 @@
+//@@author yapdianhao
+package seedu.jelphabot.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_REMIND_DAY;
+import static seedu.jelphabot.logic.parser.CliSyntax.PREFIX_REMIND_HOUR;
+
+import java.util.stream.Stream;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.ReminderCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderDay;
+import seedu.jelphabot.model.reminder.ReminderHour;
+
+/**
+ * Parses input arguments and returns a new ReminderCommand Object.
+ */
+public class ReminderCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the ReminderCommand
+ * and returns a ReminderCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public ReminderCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(
+ args,
+ PREFIX_REMIND_DAY,
+ PREFIX_REMIND_HOUR
+ );
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ReminderCommand.MESSAGE_USAGE), pe);
+ }
+ if (!arePrefixesPresent(argMultimap, PREFIX_REMIND_DAY, PREFIX_REMIND_HOUR)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ReminderCommand.MESSAGE_USAGE));
+ }
+ ReminderDay reminderDay = ParserUtil.parseReminderDay(argMultimap.getValue(PREFIX_REMIND_DAY).get());
+ ReminderHour reminderHour = ParserUtil.parseReminderHour(argMultimap.getValue(PREFIX_REMIND_HOUR).get());
+ Reminder reminder = new Reminder(index, reminderDay, reminderHour);
+ return new ReminderCommand(index, reminder);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/StartTimerCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/StartTimerCommandParser.java
new file mode 100644
index 00000000000..f63b5b635eb
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/StartTimerCommandParser.java
@@ -0,0 +1,32 @@
+// @@author Clouddoggo
+
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.StartTimerCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new StartTimerCommand object
+ */
+public class StartTimerCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of StartTimerCommand
+ * and returns a StartTimerCommand object for execution.
+ * @param args user arguments.
+ * @return a StartTimerCommand object to be used for execution.
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ public StartTimerCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new StartTimerCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, StartTimerCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/logic/parser/StopTimerCommandParser.java b/src/main/java/seedu/jelphabot/logic/parser/StopTimerCommandParser.java
new file mode 100644
index 00000000000..fe7bf0b2553
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/logic/parser/StopTimerCommandParser.java
@@ -0,0 +1,33 @@
+// @@author Clouddoggo
+
+package seedu.jelphabot.logic.parser;
+
+import static seedu.jelphabot.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.logic.commands.StopTimerCommand;
+import seedu.jelphabot.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new StopTimerCommand object
+ */
+public class StopTimerCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of StartTimerCommand
+ * and returns a StartTimerCommand object for execution.
+ * @param args user arguments.
+ * @return a StartTimerCommand object to be used for execution.
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ public StopTimerCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new StopTimerCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, StopTimerCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
+
diff --git a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java b/src/main/java/seedu/jelphabot/logic/parser/exceptions/ParseException.java
similarity index 72%
rename from src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
rename to src/main/java/seedu/jelphabot/logic/parser/exceptions/ParseException.java
index 158a1a54c1c..b4de5aa3bdd 100644
--- a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
+++ b/src/main/java/seedu/jelphabot/logic/parser/exceptions/ParseException.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.parser.exceptions;
+package seedu.jelphabot.logic.parser.exceptions;
-import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.jelphabot.commons.exceptions.IllegalValueException;
/**
* Represents a parse error encountered by a parser.
diff --git a/src/main/java/seedu/jelphabot/model/JelphaBot.java b/src/main/java/seedu/jelphabot/model/JelphaBot.java
new file mode 100644
index 00000000000..aecc1d4301f
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/model/JelphaBot.java
@@ -0,0 +1,226 @@
+package seedu.jelphabot.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderShowsTask;
+import seedu.jelphabot.model.reminder.UniqueReminderList;
+import seedu.jelphabot.model.reminder.UniqueReminderShowsTaskList;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.UniqueTaskList;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Wraps all data at the address-book level
+ * Duplicates are not allowed (by .isSameTask comparison)
+ */
+public class JelphaBot implements ReadOnlyJelphaBot {
+
+ private final List taskList;
+ private final List reminderList;
+ private final UniqueTaskList tasks;
+ private final UniqueReminderList reminders;
+ private final UniqueReminderShowsTaskList reminderShowsTaskList = new UniqueReminderShowsTaskList();
+
+ /*
+ * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
+ * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
+ *
+ * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
+ * among constructors.
+ */
+ {
+ taskList = new ArrayList<>();
+ reminderList = new ArrayList<>();
+ tasks = new UniqueTaskList();
+ reminders = new UniqueReminderList();
+ }
+
+ public JelphaBot() {}
+
+ /**
+ * Creates an JelphaBot using the Tasks in the {@code toBeCopied}
+ */
+ public JelphaBot(ReadOnlyJelphaBot toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// list overwrite operations
+
+ /**
+ * Replaces the contents of the task list with {@code tasks}.
+ * {@code tasks} must not contain duplicate tasks.
+ */
+ public void setTasks(List tasks) {
+ this.tasks.setTasks(tasks);
+ }
+
+ public void setReminders(List reminders) {
+ this.reminders.setReminders(reminders);
+ }
+
+ public void setReminderShowsTasks(List reminderShowsTasks) {
+ this.reminderShowsTaskList.setReminderShowsTasks(reminderShowsTasks);
+ }
+
+ /**
+ * deletes a reminder will cause all reminders' indexes after to shift forward.
+ */
+ public void updateDeletedReminder(Index deletedIndex) {
+ int index = deletedIndex.getOneBased();
+ reminders.updateReminderIndexes(index);
+ }
+
+ /**
+ * Resets the existing data of this {@code JelphaBot} with {@code newData}.
+ */
+ public void resetData(ReadOnlyJelphaBot newData) {
+ requireNonNull(newData);
+ for (Task task : newData.getTaskList()) {
+ taskList.add(task);
+ }
+ for (Reminder reminder : newData.getReminderList()) {
+ reminderList.add(reminder);
+ }
+ setReminders(newData.getReminderList());
+ setTasks(newData.getTaskList());
+ setReminderShowsTasks(newData.getReminderShowsTaskList());
+ }
+
+ //// task-level operations
+
+ /**
+ * Returns true if a task with the same identity as {@code task} exists in the JelphaBot.
+ */
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return tasks.contains(task);
+ }
+
+ /**
+ * Returns true if a reminder with the same identity as {@code reminder} exists in JelphaBot.
+ */
+ public boolean hasReminder(Reminder reminder) {
+ requireNonNull(reminder);
+ return reminders.contains(reminder);
+ }
+
+ /**
+ * Returns true if a task is currently being timed.
+ */
+ public boolean hasTaskBeingTimed() {
+ return tasks.hasTaskBeingTimed();
+ }
+
+ /**
+ * Adds a task to the task list.
+ * The task must not already exist in the task list.
+ */
+ public void addTask(Task p) {
+ tasks.add(p);
+ }
+
+ public void addReminder(Reminder r) {
+ reminders.add(r);
+ }
+
+ /**
+ * Replaces the given task {@code target} in the list with {@code editedTask}.
+ * {@code target} must exist in the task list.
+ * The task identity of {@code editedTask} must not be the same as another existing task in the task list.
+ */
+ public void setTask(Task target, Task editedTask) {
+ requireNonNull(editedTask);
+
+ tasks.setTask(target, editedTask);
+ }
+
+ /**
+ * Removes {@code key} from this {@code JelphaBot}.
+ * {@code key} must exist in the task list.
+ */
+ public void removeTask(Task key) {
+ tasks.remove(key);
+ }
+
+ public void removeReminder(Reminder key) {
+ reminders.remove(key);
+ }
+ //// util methods
+
+ /**
+ * adds the ReminderShowsTask Object to the panel.
+ */
+ public void addReminderShowsTask(Reminder reminder, ViewTaskList lastShownList) {
+ Task task = lastShownList.get(reminder.getIndex().getZeroBased());
+ ReminderShowsTask reminderShowsTask = new ReminderShowsTask(reminder, task);
+ reminderShowsTaskList.add(reminderShowsTask);
+ }
+
+ /**
+ * deletes the ReminderShowsTask Object from the panel list.
+ */
+ public void deleteReminderShowsTask(Reminder reminder, ViewTaskList lastShownList) {
+ Task task = lastShownList.get(reminder.getIndex().getZeroBased());
+ ReminderShowsTask reminderShowsTask = new ReminderShowsTask(reminder, task);
+ reminderShowsTaskList.remove(reminderShowsTask);
+ }
+
+ @Override
+ public String toString() {
+ return tasks.asUnmodifiableObservableList().size() + " tasks";
+ }
+
+ @Override
+ public ObservableList getTaskList() {
+ return tasks.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public ObservableList getReminderList() {
+ return reminders.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public ObservableList getReminderShowsTaskList() {
+ return reminderShowsTaskList.asUnmodifiableObservableList();
+ }
+
+ public List getTasksAsList() {
+ return taskList;
+ }
+
+ public List getRemindersAsList() {
+ return reminderList;
+ }
+
+ /**
+ * Updates the reminder list panel after adding / delete a reminder.
+ */
+ public void updateReminderShowsTask(ViewTaskList viewTaskList) {
+ for (Reminder reminder : getReminderList()) {
+ int idx = reminder.getIndex().getZeroBased();
+ Task currTask = viewTaskList.get(idx);
+ ReminderShowsTask reminderShowsTask = new ReminderShowsTask(reminder, currTask);
+ reminderShowsTaskList.add(reminderShowsTask);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof JelphaBot // instanceof handles nulls
+ && tasks.equals(((JelphaBot) other).tasks));
+ }
+
+ @Override
+ public int hashCode() {
+ return tasks.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/jelphabot/model/Model.java b/src/main/java/seedu/jelphabot/model/Model.java
new file mode 100644
index 00000000000..dfd8b798029
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/model/Model.java
@@ -0,0 +1,183 @@
+package seedu.jelphabot.model;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.jelphabot.commons.core.GuiSettings;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.productivity.ProductivityList;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderShowsTask;
+import seedu.jelphabot.model.summary.Summary;
+import seedu.jelphabot.model.summary.SummaryList;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.GroupedTaskList;
+import seedu.jelphabot.model.task.tasklist.PinnedTaskList;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * The API of the Model component.
+ */
+
+public interface Model {
+ /**
+ * {@code Predicate} that always evaluate to true
+ */
+ Predicate PREDICATE_SHOW_ALL_TASKS = unused -> true;
+
+ /**
+ * Replaces user prefs data with the data in {@code userPrefs}.
+ */
+ void setUserPrefs(ReadOnlyUserPrefs userPrefs);
+
+ /**
+ * Returns the user prefs.
+ */
+ ReadOnlyUserPrefs getUserPrefs();
+
+ /**
+ * Returns the user prefs' GUI settings.
+ */
+ GuiSettings getGuiSettings();
+
+ /**
+ * Returns the GUI settings for a popup window
+ */
+ GuiSettings getPopUpWindowGuiSettings();
+
+ /**
+ * Sets the user prefs' GUI settings.
+ */
+ void setGuiSettings(GuiSettings guiSettings);
+
+ /**
+ * Returns the user prefs' task list file path.
+ */
+ Path getJelphaBotFilePath();
+
+ /**
+ * Sets the user prefs' task list file path.
+ */
+ void setJelphaBotFilePath(Path jelphaBotFilePath);
+
+ Path getRemindersFilePath();
+
+ /**
+ * Returns the JelphaBot
+ */
+ ReadOnlyJelphaBot getJelphaBot();
+
+ /**
+ * Replaces jelphaBot data with the data in {@code jelphaBot}.
+ */
+ void setJelphaBot(ReadOnlyJelphaBot jelphaBot);
+
+ /**
+ * Returns true if a task with the same identity as {@code task} exists in the task list.
+ */
+ boolean hasTask(Task task);
+
+ boolean hasReminder(Reminder reminder);
+
+ /**
+ * Deletes the given task.
+ * The task must exist in the task list.
+ */
+ void deleteTask(Task target);
+
+ /**
+ * Deletes the given reminder.
+ *
+ * @param reminder
+ */
+ void deleteReminder(Reminder reminder);
+
+ /**
+ * Adds the given task.
+ * {@code task} must not already exist in the task list.
+ */
+ void addTask(Task task);
+
+ void addReminder(Reminder reminder);
+
+ /**
+ * Replaces the given task {@code target} with {@code editedTask}.
+ * {@code target} must exist in the task list.
+ * The task identity of {@code editedTask} must not be the same as another existing task in the task list.
+ */
+ void setTask(Task target, Task editedTask);
+
+ /**
+ * Replaces the existing productivity with {@code productivity}.
+ */
+ void setProductivity(Productivity productivity);
+
+ /**
+ * Replaces the existing summary with {@code summary}.
+ */
+ void setSummary(Summary summary);
+
+ void updateDeletedReminders(Index deletedIndex);
+
+ /**
+ * Returns an unmodifiable view of the filtered task list
+ */
+ ObservableList getFilteredTaskList();
+
+ GroupedTaskList getGroupedTaskList(GroupedTaskList.Category category);
+
+ PinnedTaskList getPinnedTaskList();
+
+ ViewTaskList getLastShownList();
+
+ ObservableList getFilteredReminderList();
+
+ ObservableList getReminderShowsTaskList();
+
+ /**
+ * Returns an unmodifiable view of the filtered task list in the Calendar
+ */
+ ObservableList getFilteredCalendarTaskList();
+
+ List getTaskListFromJelphaBot();
+
+ List getReminderListFromJelphaBot();
+
+ /**
+ * Returns an unmodifiable view of the incomplete tasks that are due soon,
+ * as specified by the user
+ * @return
+ */
+ //public ObservableList getFilteredByReminder();
+
+ /**
+ * Returns an unmodifiable view of the user's productivity.
+ */
+ ProductivityList getProductivityList();
+
+ /**
+ * Returns an unmodifiable view of the user's summary.
+ *
+ * @return
+ */
+ SummaryList getSummaryList();
+
+ /**
+ * Updates the filter of the filtered task list to filter by the given {@code predicate}.
+ *
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredTaskList(Predicate predicate);
+
+ /**
+ * Updates the filter of the filtered calendar task list to filter by the given {@code predicate}.
+ *
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredCalendarTaskList(Predicate predicate);
+
+ void updateReminderShowsTask();
+}
diff --git a/src/main/java/seedu/jelphabot/model/ModelManager.java b/src/main/java/seedu/jelphabot/model/ModelManager.java
new file mode 100644
index 00000000000..0a172104474
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/model/ModelManager.java
@@ -0,0 +1,299 @@
+package seedu.jelphabot.model;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.jelphabot.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.logging.Logger;
+
+import javafx.beans.binding.Bindings;
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import seedu.jelphabot.commons.core.GuiSettings;
+import seedu.jelphabot.commons.core.LogsCenter;
+import seedu.jelphabot.commons.core.index.Index;
+import seedu.jelphabot.model.productivity.Productivity;
+import seedu.jelphabot.model.productivity.ProductivityList;
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderShowsTask;
+import seedu.jelphabot.model.summary.Summary;
+import seedu.jelphabot.model.summary.SummaryList;
+import seedu.jelphabot.model.task.Task;
+import seedu.jelphabot.model.task.tasklist.GroupedTaskList;
+import seedu.jelphabot.model.task.tasklist.PinnedTaskList;
+import seedu.jelphabot.model.task.tasklist.ViewTaskList;
+
+/**
+ * Represents the in-memory model of the task list data.
+ */
+public class ModelManager implements Model {
+ private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
+
+ private final JelphaBot readOnlyJelphaBot;
+ private final UserPrefs userPrefs;
+ private final FilteredList filteredTasks;
+ private final FilteredList filteredReminders;
+ private final FilteredList filteredCalendarTasks;
+ private final ProductivityList productivityList;
+ private final SummaryList summaryList;
+
+ private GroupedTaskList lastShownList;
+
+ /**
+ * Initializes a ModelManager with the given readOnlyJelphaBot and userPrefs.
+ */
+ public ModelManager(ReadOnlyJelphaBot readOnlyJelphaBot, ReadOnlyUserPrefs userPrefs) {
+ super();
+ requireAllNonNull(readOnlyJelphaBot, userPrefs);
+
+ logger.fine("Initializing with task list: " + readOnlyJelphaBot + " and user prefs " + userPrefs);
+
+ this.readOnlyJelphaBot = new JelphaBot(readOnlyJelphaBot);
+ this.userPrefs = new UserPrefs(userPrefs);
+ filteredTasks = new FilteredList<>(this.readOnlyJelphaBot.getTaskList());
+ filteredReminders = new FilteredList<>(this.readOnlyJelphaBot.getReminderList());
+ filteredCalendarTasks = new FilteredList<>(this.readOnlyJelphaBot.getTaskList());
+ productivityList = new ProductivityList();
+ summaryList = new SummaryList();
+ lastShownList = getGroupedTaskList(GroupedTaskList.Category.DATE);
+ }
+
+ public ModelManager() {
+ this(new JelphaBot(), new UserPrefs());
+ }
+
+ // =========== UserPrefs
+ // ==================================================================================
+
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ requireNonNull(userPrefs);
+ this.userPrefs.resetData(userPrefs);
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ return userPrefs;
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ return userPrefs.getGuiSettings();
+ }
+
+ @Override
+ public GuiSettings getPopUpWindowGuiSettings() {
+ return userPrefs.getPopUpWindowGuiSettings();
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ requireNonNull(guiSettings);
+ userPrefs.setGuiSettings(guiSettings);
+ }
+
+ @Override
+ public Path getJelphaBotFilePath() {
+ return userPrefs.getJelphaBotFilePath();
+ }
+
+ @Override
+ public Path getRemindersFilePath() {
+ return userPrefs.getRemindersFilePath();
+ }
+
+ @Override
+ public void setJelphaBotFilePath(Path readOnlyJelphaBotFilePath) {
+ requireNonNull(readOnlyJelphaBotFilePath);
+ userPrefs.setJelphaBotFilePath(readOnlyJelphaBotFilePath);
+ }
+
+ public void setJelphaBotReminderFilePath(Path reminderFilePath) {
+ requireAllNonNull(reminderFilePath);
+ userPrefs.setJelphaBotReminderFilePath(reminderFilePath);
+ }
+
+ // =========== JelphaBot ==================================================
+
+ @Override
+ public ReadOnlyJelphaBot getJelphaBot() {
+ return readOnlyJelphaBot;
+ }
+
+ @Override
+ public void setJelphaBot(ReadOnlyJelphaBot readOnlyJelphaBot) {
+ this.readOnlyJelphaBot.resetData(readOnlyJelphaBot);
+ }
+
+ @Override
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return readOnlyJelphaBot.hasTask(task);
+ }
+
+ @Override
+ public boolean hasReminder(Reminder reminder) {
+ requireNonNull(reminder);
+ return readOnlyJelphaBot.hasReminder(reminder);
+ }
+
+ @Override
+ public void deleteTask(Task target) {
+ readOnlyJelphaBot.removeTask(target);
+ }
+
+ @Override
+ public void deleteReminder(Reminder reminder) {
+ readOnlyJelphaBot.deleteReminderShowsTask(reminder, getLastShownList());
+ readOnlyJelphaBot.removeReminder(reminder);
+ //updateReminderShowsTask();
+ }
+
+ @Override
+ public void addTask(Task task) {
+ readOnlyJelphaBot.addTask(task);
+ updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ }
+
+ @Override
+ public void addReminder(Reminder reminder) {
+ readOnlyJelphaBot.addReminderShowsTask(reminder, getLastShownList());
+ readOnlyJelphaBot.addReminder(reminder);
+ //updateReminderShowsTask();
+ }
+
+ public void updateDeletedReminders(Index deletedIndex) {
+ readOnlyJelphaBot.updateDeletedReminder(deletedIndex);
+ }
+
+ public void updateReminderShowsTask() {
+ readOnlyJelphaBot.updateReminderShowsTask(getLastShownList());
+ }
+
+ @Override
+ public void setTask(Task target, Task editedTask) {
+ requireAllNonNull(target, editedTask);
+ readOnlyJelphaBot.setTask(target, editedTask);
+ }
+
+ // =========== Productivity List
+
+ @Override
+ public void setProductivity(Productivity productivity) {
+ requireAllNonNull(productivity);
+ productivityList.setProductivity(productivity);
+ }
+
+ @Override
+ public ProductivityList getProductivityList() {
+ return productivityList;
+ }
+
+ // =========== Summary List
+ @Override
+ public void setSummary(Summary summary) {
+ requireAllNonNull(summary);
+ summaryList.setSummary(summary);
+ }
+
+ @Override
+ public SummaryList getSummaryList() {
+ return summaryList;
+ }
+
+ // =========== Filtered Task List Accessors
+ // =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Task} backed by the
+ * internal list of {@code versionedJelphaBot}
+ */
+ @Override
+ public ObservableList getFilteredTaskList() {
+ return filteredTasks;
+ }
+
+ @Override
+ public GroupedTaskList getGroupedTaskList(GroupedTaskList.Category category) {
+ if (lastShownList == null || lastShownList.getCategory() != category) {
+ lastShownList = GroupedTaskList.makeGroupedTaskList(
+ getFilteredTaskList(),
+ category,
+ getPinnedTaskList()
+ );
+ }
+ return lastShownList;
+ }
+
+ @Override
+ public PinnedTaskList getPinnedTaskList() {
+ return new PinnedTaskList(filteredTasks.filtered(task -> false), Bindings.createIntegerBinding(() -> 0));
+ }
+
+ @Override
+ public ViewTaskList getLastShownList() {
+ return lastShownList;
+ }
+
+ public ObservableList getFilteredReminderList() {
+ return filteredReminders;
+ }
+
+ @Override
+ public ObservableList getReminderShowsTaskList() {
+ return this.readOnlyJelphaBot.getReminderShowsTaskList();
+ }
+
+ @Override
+ public ObservableList getFilteredCalendarTaskList() {
+ return filteredCalendarTasks;
+ }
+
+ @Override
+ public List getTaskListFromJelphaBot() {
+ return this.readOnlyJelphaBot.getTasksAsList();
+ }
+
+ @Override
+ public List getReminderListFromJelphaBot() {
+ return this.readOnlyJelphaBot.getRemindersAsList();
+ }
+
+ @Override
+ public void updateFilteredTaskList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredTasks.setPredicate(predicate);
+ }
+
+ /**
+ * Updates the filter of the filtered calendar task list to filter by the given {@code predicate}.
+ *
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ @Override
+ public void updateFilteredCalendarTaskList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredCalendarTasks.setPredicate(predicate);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // short circuit if same object
+ if (obj == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(obj instanceof ModelManager)) {
+ return false;
+ }
+
+ // state check
+ ModelManager other = (ModelManager) obj;
+ return readOnlyJelphaBot.equals(other.readOnlyJelphaBot) && userPrefs.equals(other.userPrefs)
+ && filteredTasks.equals(other.filteredTasks);
+ }
+
+}
diff --git a/src/main/java/seedu/jelphabot/model/ReadOnlyJelphaBot.java b/src/main/java/seedu/jelphabot/model/ReadOnlyJelphaBot.java
new file mode 100644
index 00000000000..e1e9bc5a624
--- /dev/null
+++ b/src/main/java/seedu/jelphabot/model/ReadOnlyJelphaBot.java
@@ -0,0 +1,30 @@
+package seedu.jelphabot.model;
+
+import java.util.List;
+
+import javafx.collections.ObservableList;
+
+import seedu.jelphabot.model.reminder.Reminder;
+import seedu.jelphabot.model.reminder.ReminderShowsTask;
+import seedu.jelphabot.model.task.Task;
+
+/**
+ * Unmodifiable view of an task list
+ */
+public interface ReadOnlyJelphaBot {
+
+ /**
+ * Returns an unmodifiable view of the tasks list.
+ * This list will not contain any duplicate tasks.
+ */
+ ObservableList getTaskList();
+
+ ObservableList