Skip to content

Commit

Permalink
Merge 995755f into b9e2a90
Browse files Browse the repository at this point in the history
  • Loading branch information
chiaxr committed Oct 29, 2018
2 parents b9e2a90 + 995755f commit f8aeb8e
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 36 deletions.
38 changes: 28 additions & 10 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -422,17 +422,30 @@ If the user uses the `find` command, the following functions will follow the ind
// tag::rsvp[]
=== RSVP
==== Current Implementation
The RSVP feature consists the `register` command. Attendees of an event are stored in the `eventmanager.xml` file, in a similar fashion to the storage of tags.
The RSVP feature consists of the `register` & `unregister` command. The implementations of the commands use the `EditEventDescriptor` class and `createEditedEvent` method from `EditCommand` to aid in updating event attendance. Attendees of an event are stored in the `eventmanager.xml` file, in a similar fashion to the storage of tags.

Below is an example usage scenario and how the RSVP mechanism behaves:

Step 1: The user launches the application, clicks on an event or types `select 2` into the CLI. Details of the 2nd event including event attendance are displayed.

Step 2: The user executes `register 2` to register for the 2nd event. The `register` command gets the username of the current user, and adds it into the event data.
Step 2: The user executes `register 2` to register for the 2nd event. The `register` command takes in the current model and event at index 2, getting the username of the current user via `Model#getUsername()`, and the current attendance of the event as a `HashSet` with `Event#getAttendance`.

Step 3: An `EventManagerChangedEvent` event is raised by `Model`. `EventCenter` handles the event, calling for `Storage` to update `eventmanager.xml`.
Step 3: The `register` command tries to add the username into the current attendance with `add()`. If the username already exists in the attendance, a `CommandException` is thrown. Else, `EditCommand#EditEventDescriptor` is used with the new attendance to create an edited event.

Step 4: The event page is reloaded to display the new event attendance.
Step 4: The model is updated and committed, overwriting `eventmanager.xml`. The event page is reloaded to display the new event attendance.

Step 5: If the user decides to unregister from the event, the user executes `unregister 2`, and the `unregister` command gets the username and attendance in the same manner as the `register` command in Step 2.

Step 6: The `unregister` command command tries to remove the username from the current attendance with `remove()`. If the username does not exist in the attendance, a `CommandException` is thrown. Else, `EditCommand#EditEventDescriptor` is used with the new attendance to create an edited event.

Step 7: The model is updated and committed as in Step 3, and the event page is again reloaded.

[NOTE]
`TreeSet` is used when retrieving the attendance for display as it allows for easy sorting of attendee usernames. Usernames are sorted in case-insensitive order.

The following sequence diagram shows how the register operation works:

image::registerSD.png[width="800"]

==== Design Considerations
===== Aspect: How to display attendance
Expand All @@ -443,20 +456,25 @@ Step 4: The event page is reloaded to display the new event attendance.
** Pros: Easier to implement, user can easily see whether they are registered
** Cons: New methods will need to be implemented to make many fields for comments.

===== Aspect: How to store attendance
===== Aspect: Where to store attendance
* **Alternative 1 (current choice):** Attendance stored in `eventmanager.xml` in similar fashion to tags.
** Pros: Methods for parsing tags can be applied to parse attendance
** Cons: Inefficient to retrieve list of events which a user has registered for
* **Alternative 2:** Store with user details
** Pros: Can easily check which events a user has registered for.
** Cons: Inefficient to check which users are attending an event.

==== Future Improvements
===== Adding `unregister` command.
* Allows users to unregister for events.
===== Aspect: How to store attendance
* **Alternative 1 (current choice):** Attendance stored in unsorted order.
** Pros: Easy to add new attendee to attendance.
** Cons: Requires sorting whenever attendance is displayed.
* **Alternative 2:** Attendance stored in sorted order.
** Pros: No need to sort each time an event is reloaded.
** Cons: More complexity for inserting in correct location.

===== Adding `listAttending` command.
* Allows users to view events they have registered for.
==== Future Improvements
===== Adding `attending` command.
* Allows users to view all events they have registered for.
// end::rsvp[]

// tag::dataencryption[]
Expand Down
38 changes: 16 additions & 22 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -257,41 +257,35 @@ The `redo` command fails as there are no `undo` commands executed previously.
Admin: Clears all entries from the Event Manager. +
Format: `clear`

// tag::rsvp[]
=== Register for event : `register`

User: RSVPs for an event. +
User: Registers for an event, adding current user's username to attendance list. +
Format: `register INDEX`

Examples:

* `register 1` +
Registers User to event 1
* `register 5` +
Registers User to event 5
* `list` +
`register 3` +
Registers user to the 3rd event of the Event Manager.
* `find Sports` +
`register 1` +
Registers User to the 1st event in the results of the `find` command.

=== Remove registration from event : `unregister`

User: Removes RSVPs for an event. +
User: Unregisters for an event, removing current user's username to attendance list. +
Format: `unregister INDEX`

Examples:

* `unregister 1` +
Unregisters User from event 1
* `unregister 5` +
Unregisters User from event 5

=== View participant list : `viewParticipants`

Admin/User: View names and total number of event attendees +
Format: `viewParticipants INDEX`

Examples:

* `viewParticipants 1` +
Shows total and names of all participants going to event 1
* `viewParticipants 5` +
Shows total and names of all participants going to event 5
* `list` +
`register 1` +
Unregisters user from the 1st event of the Event Manager.
* `find Sports` +
`register 2` +
Unregisters User from the 2nd event in the results of the `find` command.
// end::rsvp[]

=== Set reminders : `setReminder`

Expand Down
Binary file added docs/images/registerSD.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions docs/team/chiaxr.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
= Chia Xiang Rong - Project Portfolio
:site-section: AboutUs
:imagesDir: ../images
:stylesDir: ../stylesheets

== PROJECT: Event Manager

---

== Overview

Event Manager is a desktop address book application used for managing events in the Halls and Residential Colleges of NUS. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.

== Summary of contributions
* *Major enhancement*: Added *the ability to register/unregister for events and view event attendance*
** What it does: Allows users to indicate their attendance for events, and view the usernames of other attendees.
** Justification: This feature allows event ICs to have an idea of the number of attendees for planning purposes, as well as users to see who else is attending the event so they might connect with people they know.
** Highlights: This enhancement affects existing commands and commands to be added in the future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands.
** Credits: -

* *Minor enhancement*: Created EventSearchPage to display all event details on selection.

* *Code contributed*: [https://github.com[Functional code]] [https://github.com[Test code]]

* *Other contributions*:

** Project management:
*** Managed releases `v1.3` - `v1.4` (2 releases) on GitHub
*** Wrote additional tests for RSVP features to increase coverage (Pull request https://github.com/CS2113-AY1819S1-T12-1/main/pull/99[#99])
** Documentation:
*** Updated User and Developer Guides to describe new features: https://github.com/CS2113-AY1819S1-T12-1/main/pull/81[#81]
** Community:
*** PRs reviewed: https://github.com/CS2113-AY1819S1-T12-1/main/pull/22[#22], https://github.com/CS2113-AY1819S1-T12-1/main/pull/58[#58], https://github.com/CS2113-AY1819S1-T12-1/main/pull/59[#59]
** Tools: -

== 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=rsvp]


== 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=rsvp]

Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ public CommandResult execute(Model model, CommandHistory history) throws Command
String attendeeName = model.getUsername().toString();

Set<Attendee> attendeeSet = new HashSet<>(eventToRegister.getAttendance());
int numAttendees = attendeeSet.size();
attendeeSet.add(new Attendee(attendeeName));

if (attendeeSet.size() == numAttendees) {
if (!attendeeSet.add(new Attendee(attendeeName))) {
throw new CommandException(MESSAGE_ALREADY_REGISTERED);
}

Expand Down
81 changes: 81 additions & 0 deletions src/main/java/seedu/address/logic/commands/UnregisterCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.commands.EditCommand.EditEventDescriptor;
import static seedu.address.logic.commands.EditCommand.createEditedEvent;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_EVENTS;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import seedu.address.commons.core.EventsCenter;
import seedu.address.commons.core.Messages;
import seedu.address.commons.core.index.Index;
import seedu.address.commons.events.ui.JumpToListRequestEvent;
import seedu.address.logic.CommandHistory;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.attendee.Attendee;
import seedu.address.model.event.Event;

/**
* Unregisters for an event identified using it's displayed index from the event manager.
*/
public class UnregisterCommand extends Command {

public static final String COMMAND_WORD = "unregister";

public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Unregisters for an event identified by the index number used in the displayed event list.\n"
+ "Parameters: INDEX (must be a positive integer)\n"
+ "Example: " + COMMAND_WORD + " 1";

public static final String MESSAGE_UNREGISTER_EVENT_SUCCESS = "Unregistered for event: %1$s";
public static final String MESSAGE_NOT_REGISTERED = "Not registered for event.";

private final Index targetIndex;

public UnregisterCommand(Index targetIndex) {
this.targetIndex = targetIndex;
}

@Override
public CommandResult execute(Model model, CommandHistory history) throws CommandException {
requireNonNull(model);

List<Event> filteredEventList = model.getFilteredEventList();

if (targetIndex.getZeroBased() >= filteredEventList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_EVENT_DISPLAYED_INDEX);
}

Event eventToUnregister = filteredEventList.get(targetIndex.getZeroBased());

String attendeeName = model.getUsername().toString();

Set<Attendee> attendeeSet = new HashSet<>(eventToUnregister.getAttendance());

if (!attendeeSet.remove(new Attendee(attendeeName))) {
throw new CommandException(MESSAGE_NOT_REGISTERED);
}

EditEventDescriptor registerEventDescriptor = new EditEventDescriptor();
registerEventDescriptor.setAttendees(attendeeSet);
Event registeredEvent = createEditedEvent(eventToUnregister, registerEventDescriptor);

model.updateEvent(eventToUnregister, registeredEvent);
model.updateFilteredEventList(PREDICATE_SHOW_ALL_EVENTS);
model.commitEventManager();

EventsCenter.getInstance().post(new JumpToListRequestEvent(targetIndex));
return new CommandResult(String.format(MESSAGE_UNREGISTER_EVENT_SUCCESS, targetIndex.getOneBased()));
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof UnregisterCommand // instanceof handles nulls
&& targetIndex.equals(((UnregisterCommand) other).targetIndex)); // state check
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import seedu.address.logic.commands.SelectCommand;
import seedu.address.logic.commands.SignupCommand;
import seedu.address.logic.commands.UndoCommand;
import seedu.address.logic.commands.UnregisterCommand;
import seedu.address.logic.parser.exceptions.ParseException;

/**
Expand Down Expand Up @@ -104,6 +105,9 @@ public Command parseCommand(String userInput) throws ParseException {
case RegisterCommand.COMMAND_WORD:
return new RegisterCommandParser().parse(arguments);

case UnregisterCommand.COMMAND_WORD:
return new UnregisterCommandParser().parse(arguments);

case AddCommentCommand.COMMAND_WORD:
return new AddCommentCommandParser().parse(arguments);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package seedu.address.logic.parser;

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.UnregisterCommand;
import seedu.address.logic.parser.exceptions.ParseException;

/**
* Parses input arguments and creates a new RegisterCommand object
*/
public class UnregisterCommandParser implements Parser<UnregisterCommand> {

/**
* Parses the given {@code String} of arguments in the context of the RegisterCommand
* and returns an RegisterCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public UnregisterCommand parse(String args) throws ParseException {
try {
Index index = ParserUtil.parseIndex(args);
return new UnregisterCommand(index);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, UnregisterCommand.MESSAGE_USAGE), pe);
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/seedu/address/model/event/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public Set<Attendee> getAttendance() {
* Returns attendee list formatted as a string to be passed into Event Page HTML as query string parameter
*/
public String getAttendanceString() {
TreeSet<String> attendeesSet = new TreeSet<>();
TreeSet<String> attendeesSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
for (Attendee a: attendees) {
attendeesSet.add(a.attendeeName);
}
Expand Down

0 comments on commit f8aeb8e

Please sign in to comment.