From fdff5f47ef1eafa74d6bea9073e062315d6a85dd Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 16:40:28 +0800 Subject: [PATCH 01/10] Display attendees in case-insensitive order --- src/main/java/seedu/address/model/event/Event.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/model/event/Event.java b/src/main/java/seedu/address/model/event/Event.java index 2572483179c3..c76b4be0ee47 100644 --- a/src/main/java/seedu/address/model/event/Event.java +++ b/src/main/java/seedu/address/model/event/Event.java @@ -113,7 +113,7 @@ public Set getAttendance() { * Returns attendee list formatted as a string to be passed into Event Page HTML as query string parameter */ public String getAttendanceString() { - TreeSet attendeesSet = new TreeSet<>(); + TreeSet attendeesSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (Attendee a: attendees) { attendeesSet.add(a.attendeeName); } From 8372ac4b5b07dd55c0d5b417fbe420bf0c9adec2 Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 16:59:41 +0800 Subject: [PATCH 02/10] Add stub Unregister Command --- .../logic/commands/UnregisterCommand.java | 83 +++++++++++++++++++ .../logic/parser/EventManagerParser.java | 4 + .../logic/parser/UnregisterCommandParser.java | 28 +++++++ 3 files changed, 115 insertions(+) create mode 100644 src/main/java/seedu/address/logic/commands/UnregisterCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/UnregisterCommandParser.java diff --git a/src/main/java/seedu/address/logic/commands/UnregisterCommand.java b/src/main/java/seedu/address/logic/commands/UnregisterCommand.java new file mode 100644 index 000000000000..3fce634a8222 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/UnregisterCommand.java @@ -0,0 +1,83 @@ +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_REGISTER_EVENT_SUCCESS = "Unregistered for event: %1$s"; + public static final String MESSAGE_ALREADY_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 filteredEventList = model.getFilteredEventList(); + + if (targetIndex.getZeroBased() >= filteredEventList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_EVENT_DISPLAYED_INDEX); + } + + /*Event eventToRegister = filteredEventList.get(targetIndex.getZeroBased()); + + String attendeeName = model.getUsername().toString(); + + Set attendeeSet = new HashSet<>(eventToRegister.getAttendance()); + int numAttendees = attendeeSet.size(); + attendeeSet.add(new Attendee(attendeeName)); + + if (attendeeSet.size() == numAttendees) { + throw new CommandException(MESSAGE_ALREADY_REGISTERED); + } + + EditEventDescriptor registerEventDescriptor = new EditEventDescriptor(); + registerEventDescriptor.setAttendees(attendeeSet); + Event registeredEvent = createEditedEvent(eventToRegister, registerEventDescriptor); + + model.updateEvent(eventToRegister, registeredEvent); + model.updateFilteredEventList(PREDICATE_SHOW_ALL_EVENTS); + model.commitEventManager();*/ + + EventsCenter.getInstance().post(new JumpToListRequestEvent(targetIndex)); + return new CommandResult(String.format(MESSAGE_REGISTER_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 + } +} diff --git a/src/main/java/seedu/address/logic/parser/EventManagerParser.java b/src/main/java/seedu/address/logic/parser/EventManagerParser.java index 25fc2a23830e..b84aad56405f 100644 --- a/src/main/java/seedu/address/logic/parser/EventManagerParser.java +++ b/src/main/java/seedu/address/logic/parser/EventManagerParser.java @@ -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; /** @@ -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); diff --git a/src/main/java/seedu/address/logic/parser/UnregisterCommandParser.java b/src/main/java/seedu/address/logic/parser/UnregisterCommandParser.java new file mode 100644 index 000000000000..a8d3d3a0027b --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/UnregisterCommandParser.java @@ -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 { + + /** + * 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); + } + } +} From 23acbaf6aba13e20456a3a60e40909da1b952459 Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 17:09:41 +0800 Subject: [PATCH 03/10] Implemented Unregister functionality --- .../logic/commands/UnregisterCommand.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/UnregisterCommand.java b/src/main/java/seedu/address/logic/commands/UnregisterCommand.java index 3fce634a8222..d8c38e688be0 100644 --- a/src/main/java/seedu/address/logic/commands/UnregisterCommand.java +++ b/src/main/java/seedu/address/logic/commands/UnregisterCommand.java @@ -31,8 +31,8 @@ public class UnregisterCommand extends Command { + "Parameters: INDEX (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 1"; - public static final String MESSAGE_REGISTER_EVENT_SUCCESS = "Unregistered for event: %1$s"; - public static final String MESSAGE_ALREADY_REGISTERED = "Not registered for event."; + 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; @@ -50,28 +50,26 @@ public CommandResult execute(Model model, CommandHistory history) throws Command throw new CommandException(Messages.MESSAGE_INVALID_EVENT_DISPLAYED_INDEX); } - /*Event eventToRegister = filteredEventList.get(targetIndex.getZeroBased()); + Event eventToUnregister = filteredEventList.get(targetIndex.getZeroBased()); String attendeeName = model.getUsername().toString(); - Set attendeeSet = new HashSet<>(eventToRegister.getAttendance()); - int numAttendees = attendeeSet.size(); - attendeeSet.add(new Attendee(attendeeName)); + Set attendeeSet = new HashSet<>(eventToUnregister.getAttendance()); - if (attendeeSet.size() == numAttendees) { - throw new CommandException(MESSAGE_ALREADY_REGISTERED); + if (!attendeeSet.remove(new Attendee(attendeeName))) { + throw new CommandException(MESSAGE_NOT_REGISTERED); } EditEventDescriptor registerEventDescriptor = new EditEventDescriptor(); registerEventDescriptor.setAttendees(attendeeSet); - Event registeredEvent = createEditedEvent(eventToRegister, registerEventDescriptor); + Event registeredEvent = createEditedEvent(eventToUnregister, registerEventDescriptor); - model.updateEvent(eventToRegister, registeredEvent); + model.updateEvent(eventToUnregister, registeredEvent); model.updateFilteredEventList(PREDICATE_SHOW_ALL_EVENTS); - model.commitEventManager();*/ + model.commitEventManager(); EventsCenter.getInstance().post(new JumpToListRequestEvent(targetIndex)); - return new CommandResult(String.format(MESSAGE_REGISTER_EVENT_SUCCESS, targetIndex.getOneBased())); + return new CommandResult(String.format(MESSAGE_UNREGISTER_EVENT_SUCCESS, targetIndex.getOneBased())); } @Override From 7b5801a4f2d315dec2eb277d59ecd884113bd47c Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 17:10:28 +0800 Subject: [PATCH 04/10] Minor change to checking for prior registration --- .../java/seedu/address/logic/commands/RegisterCommand.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/RegisterCommand.java b/src/main/java/seedu/address/logic/commands/RegisterCommand.java index 86696991cc2c..231027e41c11 100644 --- a/src/main/java/seedu/address/logic/commands/RegisterCommand.java +++ b/src/main/java/seedu/address/logic/commands/RegisterCommand.java @@ -56,10 +56,8 @@ public CommandResult execute(Model model, CommandHistory history) throws Command String attendeeName = model.getUsername().toString(); Set 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); } From 1f88e863ddb6af2f88f967e83d2e226b53a443cd Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 17:35:48 +0800 Subject: [PATCH 05/10] Update User Guide for Register and Unregister Command --- docs/UserGuide.adoc | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 5dcb12ccbcc7..e1df7c9ea9a6 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -259,39 +259,31 @@ Format: `clear` === 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. === Set reminders : `setReminder` From d6dc1fda21be8873d1c5f3dff0a98096479a57e7 Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 18:54:21 +0800 Subject: [PATCH 06/10] Update Developer Guide --- docs/DeveloperGuide.adoc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index a55e354c2f2f..e3a28bb0cda6 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -422,17 +422,23 @@ 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. 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. ==== Design Considerations ===== Aspect: How to display attendance @@ -452,10 +458,7 @@ Step 4: The event page is reloaded to display the new event attendance. ** Cons: Inefficient to check which users are attending an event. ==== Future Improvements -===== Adding `unregister` command. -* Allows users to unregister for events. - -===== Adding `listAttending` command. +===== Adding `attending` command. * Allows users to view events they have registered for. // end::rsvp[] From 7d3d116247614efcdb438728dda8fc02e0f084d6 Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 20:45:36 +0800 Subject: [PATCH 07/10] Update RSVP intro and add new design aspect consideration to DG --- docs/DeveloperGuide.adoc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index e3a28bb0cda6..807aabde7e0a 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -422,7 +422,7 @@ If the user uses the `find` command, the following functions will follow the ind // tag::rsvp[] === RSVP ==== Current Implementation -The RSVP feature consists of the `register` & `unregister` 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: @@ -449,7 +449,7 @@ Step 7: The model is updated and committed as in Step 3, and the event page is a ** 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 @@ -457,6 +457,14 @@ Step 7: The model is updated and committed as in Step 3, and the event page is a ** Pros: Can easily check which events a user has registered for. ** Cons: Inefficient to check which users are attending an event. +===== 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. + ==== Future Improvements ===== Adding `attending` command. * Allows users to view events they have registered for. From 77eb03f6ccac74bb5ae1a9f5edf01a7af177aa32 Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 22:18:17 +0800 Subject: [PATCH 08/10] Add sequence diagram for register to DG --- docs/DeveloperGuide.adoc | 6 ++++++ docs/images/registerSD.png | Bin 0 -> 41849 bytes 2 files changed, 6 insertions(+) create mode 100644 docs/images/registerSD.png diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 807aabde7e0a..571d110bd690 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -440,6 +440,12 @@ Step 6: The `unregister` command command tries to remove the username from the c 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 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 * **Alternative 1 (current choice):** Display event attendance list diff --git a/docs/images/registerSD.png b/docs/images/registerSD.png new file mode 100644 index 0000000000000000000000000000000000000000..d70eec08cea47d2a3e3320d7e331166561f64ea3 GIT binary patch literal 41849 zcmeFYcT`i|*De|hf+8X+pj3fZQ97?mZ&H0#M5OnoQUgM$fe=&#r0S~_rGz3yswgc$ z5|k39g%&_UQILcH0VyFQA>{0M#{GTYxaa(F#~JtjcNrstowe6qnRBkW)}GIN=6Zhj zjv3!Ekz*hbi0_{p#`i!VE(i#8aEIpz&~j*piwOKX0J&#o2&x?vBLiO!dtW!d4g%F@ z@a}nV0pE{4y5RskaiWv+Ie-nSxDPZ+g__uh8ihRY2=xsLJa6p_egOJgMO8yfRYmJ> z&GUc%&ACufKjx|)3IY}X{KxpZb)@U+%+Wltus8bq%IA+FZ)p7c=rB+D`IFK=Ur<5T zIzoJ3lPCCx1w&mT91JE{{@dlXRZIKff-hWL1b=&?9tjjL$;lO7;yL^;=*XeRpr1Fs zywv{7nXQAT=8s*~ef6gQ_Q=dutUqem32%eP>*@~t8nw`G?1rrT1xO15y`9Qh6ysdP zUA)-O(F){q;EVI02BGu+Z#FpTG~dxI4_HPqf3^B{FPEo)gaN6> zg)&iz3!~EeaIv5RdO}qCF3LCB*T@ zr+wii3Gc+s_%CNyG(YmV$**6{tu*xZ;_Vy0d%GbXGDjh~#)q3Tl;LuUE|=;2^GZ-pbLg@!u5HN-?AK|=}SwKXo&_3H7++#4rCxI5vG4gjia(C4y)RVm?u_?8qQKz*rbr|?Ms z@z=bf=ljLa4|iVLe=7GC5Z}G9(W>tm59Gj++zYpQKOfJx?oJK?sU&T0qbza=IOz_&49CaJ71_}Z`0j}`;NgN;`Rl-~VzWT)m{WjT7_5Ao zI|F_&r2u+rX`%o16mh3SHmeTYSCzz(UCXvEs%)2b8B}AG)Aqc(9Fd_c%n|tmUAHw9 zysH@&WTCpvur}F^IhJ;Gj!fxKuyo>2AjSY5AB3 zoCzcfvIA}64-ZMiBVi|PkV;TsM>V)2UkS;UH$LdY{bf4s3|rN?sn-O@89P>KijUJ( z^zy#Zl0V0*8lDuJ{|G@r4mjqkM9947I7MNmPa|lE0rc|VENi@f!R2hAXCd7rtTrg; zV1t^+nyLN!iIYH^;*BsR1OL;+z{83{obgSR;*ShX#UoK?6oq0GIr7=Q!yn}I*cqvm zg(V;5*!EsN?@%kyXZx2U!kuH#*1a~N!my)|=*xh`fgV+kjl?&Av8n`!JBHhWBThV= zfy#oE3|4@tcv3mNmLIw|?2DN(Emhvfz?CL|hlWzO2f%!oy+zunMFi#ju$v-4ut_=Ex1B#Zv}sz-oZ{#s1kYQQ)`Cj?L}QaK?QkFu`#T zw^QMBJ6}^=L+w@B!x`v%{VS}^Z2e2b(-&7=`VSm=3+OskbA2y0x7NZN_G5^@eaIniA%2 zhNooO#kS>mM`=Epeko%nyim#GjMG>MBj0jkutyO4p%7%#c$3t4H`rnOJB-cDpj2%0 zS@Okfbdz4+TCvG+0&kpT_NX#Gc`Faa0B$*?#IASR>{=jOjSedHw5`{BGpOr9@>4P~ z>mS|9hD)$#R@jTDC6$Oj{n_+qp8NY(_Uk7D8Or;26%y;!u0s36yP+JD>VgkPuZ>yxv-Q$HT(ukR(c!McO2YkA>x5z9kR&EQ`*$6gn2WfD z*{7C}2ZHtqo-WfneQvRsvv86&dv>^-mIp!G1!#k(;DUYBN~|t>Pd)`)*W&3apoLYP zw>My(BAzh(6o`6XlDxADXBba`Y0tYOdw-ghHX|IF$NsVYIZH1mBnQv#EP1(E_0!

fY9>8V1iG;v5 z7by7_`{UUOCcaKdktp!70J^L%xG-E2aRbh5X5UNgyf)$N+8@;NGrL;{x{W4Y3zF}V z&EHlh>#o1CO|9At&d^$J6sMt9YNKli`><{e?k=yT+ibEQ_Q z1A9lAd33aD#?DbDCE|u^;9qVUinQ+oo|=_@M%Ju^+9sEJPhU+(AE;`z!~J%I4Xoi=^=8FJ^I* z^0xMi>nK&Ojb04S23Q@vmCIH$FWCF&=?tDYnTe?fufB?=+M>4d*^|N3?cm$%k=S49 zUYwaDB$%e2bx3dBnZ@YJ!&pxGa&nJ8@qkP80~;(R*(Th=E2e2vYLq53ioc|d0Aqhu zmi=m$o`qShXc;I9YV@Q%Wp97mCgbwwhKr?)Qxeu)n$Y=&fVsVz^0U({vt)2VCPSxI z#yCxg8);%V>03V2H_U()zolXI(N#QPh=2Ua0~AeCj56$(jGNNLyJDBlXTtlnGVN*1 z=Pad`A8_rpE0XGKH0?Pg@@H_lIkPTw`90fO!48Ll#v1q&=8<8&s-ll3o(L}b{N82Q z4a!$W%T%xi`QhWh8lg&knQG48Ebu%In9hGP;!6VWW3|L{S9%Y0oWJtmrsh&YuXAfy z=X#wYu>>2CZJJsQs}vSCshWz)cIguUv;e69A${n|1!djV9J36<^p+ZwM68_lK|I=) zcXQ(G2cWpeGX14a!%nnm_MU0^Y%AdHK6Q`2XEye_a0YO9C%+-^KCSoW1f!IHaL#eW z;y>3QgWQuuVEYE*4v+`uCdh#I|8Mv|wMU#{fm6BIrvnj+_Lk{ts8_i54`QEx1e59I z*(Ku(5kihe@)#V*z>T8qabMF<>B_^`hvKe3?0p?F#OD#H9I&PmvD($ycfkjqLYf=f z^r)S4@CmHh*E{Po_Wu=3{V(iWdI3dV)Gn_={~p;M$dGWX{o`ai zO#pO$?WOjkmP@{OxGZAxjc{50X@2GGw|$?Z!MW(&2<~!CnxX~!cj@=VsmFpIYutCH z<#l(Lmbce%Gxus|K3HH#aiL?63Bn5nc|nJJJihmqkGjF;GrDuky*Bo8M@mTuSEa^+ zhxB|F!b0**llaDykoTYDYoj$-*o^hd*=iXYn7eFd=A7Nf1-)%%$k=4|zQ;W+_YBMK z-M;L(SFw9-i76ZImasjW+)Wr#u#v$$4%)_}Pn%|y5dZcv)dZcrUv~R4_srclw{9gD zUi^|jdl*R-;R3dmy#$_+wqu=zf?fU^v2M%d1LD7Sdgd^`bs^g^0((8{5S_sfE9srd zbocGg?Dm=kl4w!5jzLhNq@tZfQTUn26-&Lt>Qvvc1apOe;hRQylKA_F7Q>)rgzMt;0GuLaU z{tBgL{yZt@Ju~CIJzQf;v}yiEk`(kW7i*5LueD^x^XT1){65$nu9~sX&9Yq-I_?mE z5z!KP2idS6^_&_$`;l~dk{_BM6^57(R=aiU zC|C$u&SZWPdSpnH|aVw8pB5C>z!~q&+BAq$zB}zH;5lg{3!!!3C^FJJ@1e zN){HeQPi3g?OBUWFYxxKW5^5UR8&zj&Ma2){r+C%x}uA&86IqS1*g4YHK4-)hvH#+f%Xn@|zfO8o>{^}iqa~KGtl6#cq^jNg_C};kPGz7lE&ot$ zyGx#T($+T*b3JTJUAv1;MsT|+Y4?4E@ygE;e+dO*S|wy_-7Hp& zI-iG4UEM1s?H6iJP7sRnCFEnSpmz!6}(GKlF-TU-N z)$WiJ^HrX(_)k%74E|`fcj`E^B0>jy1D1M; zwdjxeOsZ|wTu4$YbC-nh(pmE}c-frRp^>tc;$>@M<24!7OhsgoAT@ey`i2DTYkId% z*OoZW0bTb3f#q2cc^`Od<@tnHd&07tndqrHQe>K`)62>|DYN)2DZ|lS)K|UgXh@0xNc`;JUJueov(zHE25MaNS1B0!%6eYXh@* zPFa~NfihgP=9=}W1A`d2Kx_|VIZ;z;eDQ9J>}IrSjQ06$B0Y(jjCF$ruDA(HN!U?y z{$rB^!bPU>2RHcXQ0ny&y|(mA#FPSitNv)2Cu3`d`A~dZg~(Vtjqh|y)QRY5xi#&| zCo9*W(=K4A%tM8dYah>I(KFw05!S8vzLm-h^)c=r4cU>p#-;beDsAue_+M>$k5&pP zU2FU#p-7|~J!8z(wTs~kY|>n5mT%l(x-`=h{8dH4hf@Sncbe=1W8v=;Djir0DMI{G z81=9VY*!-bL;3mxI!vC8_NGTkHqQ)s7Ibep^8MR(`ud}G44(TVwKZC=mGPsN;bEOg zljOYeFZ4g?SiCF4a8SF4>X@A2uT>yY5A-BF!JQ;*?|44YJl`vP_n78h1;5?f>+yP2 z4|^Es6=J<2u8RM6Yh`i?s(a<49fkN_WMol@3qSWX=0FF7UvSyYN)>!ev!mK}hgdoK zuzGnF@InPF#EG3}8_h>EUCquA0P_`(v{V^{dl_HKtIAx^TXwo0$p+pKXYIc@zr9(T zRkL5BU)d+Ux>PCq(9PK3%yqjHNg?>Tgf)4&zU8OMj2Df~#l0W)bEun9HdUu(hLW*& z-D-s0x@-A=Z;qv2zm{upICMj#7i<_3_JCToU1WJFuYCXb@wQVG(0u!R#Dzgs`0tNW zmd~77sN@%)>ZH4>B|f3KjDu$TJljlhzPC|)l~t&AFF)&-gb9*N?0E31#(Jbqa4IAG z)+#5t~`o{GcD_D=zqnEOjssg zJ(F2#w(+0n$y<1@@xIUC#%0B;tv+|{aOzi2VYrdK+ICCh?7{B!Z$xVfBp(-SB-w7f zBy!#V+OJh}+;=GbY2ICyOAUW!^pbjF?l|CY42_wqHdR6nsqu9W*J$~Fn>5!5g z%LXHnZxSbRz_J$9FT9bQa$vDgs;uBJ5_wZ0{ky2<`DB%AJ9Bq6UPmYHcwg{b%S9H+ zweut{SM4r8on9*lTDrNfo5U|aPqml4L!29C9P2l~Y}aOb_MD_oS4$heYsj-;s`PzW z=3I%|7^xBPI6VKWBU1)Cl0{RqJxn0U(9v;_w#WkfCmEUG&v6&o8|+kkLZ6&daMis26SsM;MW+&4o=@yhUSH)1{)rBedN&e`H_ORKH+S!gG zKi`kko7XMfhv~Q~Uwr%nir%^Rd$H;MwZi(c<&8LdNbw1d!mbj?CMLwPwvE1A5tVp`w&is2gns8NyaN zlEDRZ4OVF#&TOx}l8KG#@h@hWbFFhw>mlzH()eX;K!*#j?duZr^YJ+|BQIJxnXzQd}#6q?7}w_@;6FPX_dE9>?|dS zz$7!y2)1 zWtwoG`W|_s;cswj$`zX$$IZLYz7;2${C7aroq=eb%$?ZbTJmF)s?q3u&rmJK%iNI< zMkgBDpJ&O=!C+87gm4*R@8?U>OziSYLRn26!^9Ca5i1JY3wN8HAJiV5S(#lq;#l=R zk-!Jai;yvAiP;uq*nx(2m+(KKDS=lGf>^&|7pnlKtt0-yrHbT_xUs{a#P6h$7i{UMV)kgu^M%o=2()f3I9rd8HSIlunwWc; zCAmKm+lC2u+MoS;*>^lpS;=kSkl6zz(9`^00C|qQ>U9R-4i5wo^y{r4*)3K}5!|>a zME+FAxZ$W7YK_Roz(&1CDt;>8AdAl3@a@leJ-b~tkG}Jrw9Z)EtwHZCXzRJ@Na9J} z^vd$lxjR~)+|u1#Tw5p|ZXOuppfZV_Lm+2nqA@TZ$QD(ork*F+nVUIwz z#;?at+BO=FP185~4w>ihcDT!OK-rh+*o*zo%*}Fmk6#54^wWG5;X>s0U;Q&5^Eep@ z&`=jJGUrdxAO|2GfQEzr2MtY;f%zf*N2VLyO*E&r@91rP3F#_R2_S5czX@iPkqTgC z&Yi?Z|4)JDAn^KIk;KGAGq!!X-~BXdmYV>*3ti;n9o7eng|J(;bzjEsWw*&6{7YKcJ#JOGqXp4I& z)Boq%r|ZA^EJ;aj1NS~?9tD2at{M;xRQMf`;qlybt456w@nG107liShkM~b5B>?*0 z$9JXA*Zbzkk8@^f$e1ITJimBu0x#sT78V)=G`e3oMLcN0FV6mVV-X-dfPArs($ycy zRNxYHRTQ{>)R`wcvT$o6>lWym-V&goJLJz3tkr~P|9OJbo0C^DJfy7Y-qyfcl3F~) zX$y$`;_UMyGcnz~GcnLc>A;xS3JMq^ZouciZSFEtpTBv#+NZ0{a=>vq@R(!Y|B7b; z8taKlbK_nxJ#TxZwE0~`S~Pen>}&es6ji!kTzlhp$a|U)4)YJk2OAXrYj(kuTwb=i zcr@WVIgg8-FX7DeK?=Dq>=CoNIZSo$1>pB48{(12j~TiY>hBT9yL}r~ICR~>{St!0 z-WCG>VlbEXD#Z6u*WygV!-nKx(ZB}-ySoVkCAJf!pAa@(wu&mOZzPggdYT1B&Q|48OUxFW52gZa;*&EBg0 zWS`jrvM_gny$7V?^PaO_4^2JvP-*r5oE%~-zq_!hNzRAhqFj@5k3tTB;y&Nb;T>{r zaB#odM>&K3G}qu+c?1a(T~PnC0CcQ?r2*Hi?w);$n;j1-j(f@&b>7CU5`m zmi3TPUChSh)qo}2KQkWS2zcL8k)4E=8lNyH@AlyhK$db`!7&ct7w^zNPdCg7KYYhq z3vY2Yf=R+Up|I4Jn9&J69A4%iQ5?(lcViKK`$Ri;Wx7U;UtUKiJ zzXFWSm<_QW$Tj*Cr<6s;qrFK~&zY^NwboT!e(ML>=@yFn#;OY$0MFqF5P}K|r9R=t5rX12q+6NaiA)MPTwf(WC1;?sBTu=4- zU0iMBYV8Tkx`A2rqX(*U5m=9IonJpfNR~!gauL`Jv3vd8Qx}3}lm}QtueZAwXbKad z%66Sfun>3j-|d_4y+=fM=Ja4Ru(HD7$|P#SPS$O|+>w78(H|wvC;9P#*2;snGlFdb z@t6lA=_X0J6y%Ircg*a9g%BieVDbOvwSN{iYYnEKmm3SkdXaxV@E`pe#@^L^h)^ZB zpQhc3Ue{1aV|)$kwj<9)j}4OjgT5;dM2CjG-CMts9EQ>L3W3sHOGc3sN;ll-EF*Gl zcU8)QIEt1NN*r!0Qx|Xdsu!!I)o(Q!jU>7uowS%sM@_mZ!gUTW%2w6nX7)ZCrGViv zgc9<*l=VwJxcul)t<{v~cjx%WptBF7m>P&rN{H-QWb{A5cY;^5EvD6A#1`FTO7X{S z@i{g`bsz7`9oFEGWXnBlM$@;L)Sf}EwU_*Tt@4hH4IF2^ybIch?$ZyIA!IlFn|j^6J-A_wEmRb%$FGaaP{EhIe(ecvrA+jdN}+z2Ipw_+#X8%bzhry8`5oRy)cQ zJ2Sw>n$vSfr`>rO)x8yTGrIr|MIHuT1&%xUAJ9oOAJuzJ*^Of~uaZBsT z^dn091@agh{b^FKed7y3d&aEa3-Lleu&Th`hItbnVS3`djdOQY54}h8nMU~GWTYgx zG0fnElTmGY+K(#-d(V>2s~bm(S~ZAN*!J`UFYIboq!Fa!by*+Vk{5Xly$}LMO$twj zDk5vLnF9}p>zbhbIc9OwnZtwto5RRpeLPn9GbIro8)W7mAES>KI%fH-O$y!;Oundwbw0q@?ni;nbsHf~&ptXVXTob+f64sNhF84UhGP z^+^vCd+5&MR`Ol7%7~H>bz_sjq~4iH_F9Ixr8Ti$&BZFTh9<}k6C^ewLzx++W%zfAc{@(T5p{BP|Q%v`V@l@ zs5J#->ChNA!3VEO{tO8eec27eqU#5kC+6Ne6YO;o_Rh*A)izmzd;~Gb2f>c`ADxDP z%9Ce~{MC;NcdZFg%iCe;3k#o(?&i9pE$2hZMp@`@R?ehE1&00JF~SNeo;9rfn)X6{ zXO8qqT__VNm2OotndYw1PWqZZGVN=2W&xe^>5+|U2J`t=Ix_<+AU)O&|Hi1qr%}-| z;YtSwasm~U-w74-U3Y%1;HdE{d5Y`S#Jg|W6JKzm6S{W8;pgpmGUSy{jNfQbP3pKN z=U;;Aw29DvSqAX<^6}2TqJpSki8}PsjwkyCPB!JP+LNCZw`*->CsNL<%S9V)4^Vt9 z+~OW?`gLDhZ?q`VB9rIiBx=)j2Z* z1R6{;{jK{=9|YJHkL-MTwL|gw_JW}HEBq*`Q8h!C8!7O_>;)5lnszzp&pQk1W$^De zzpAIx4~w)+xWEmbyUlYtz;p{DrKT=A?_tf7gBvt>kOPKc$-HG?^>!hi#Fj~iq;Xzm zKEz8^!sZAX?%GgkFG-_SAuZ0Vh&b3D>8q#ImiXJ0;njEnGWhWu@Aj4o!!)&{4sP;c zRoGrd{z@xr%>L4jS&G3`CHJfevyAU+Q-a1^>x*!xLOylGC3!2oi7z63(&v3$d zW02@$e~ZvY+&|gVZvx#~J~}TeJQ?G8SR&mlC-)%3IRY)I{jgcueGr>;UhT<*DKmZv zD=PK-7TZ6(eEeweo#EW(VLd4XgvAP7d@b2e@fp6WJg9q+Sg=H9QOEzcd)C!9?(7=# zwk*jrfz?ZInExJXw&+w}P&b}zn8ygJoTZC$A4!DCUL`f&emJ)O{kY1~Z3p=CDkVPq z9MQ}VY(_43vLC^Z8SnG*_a~b8G~ft}D}6MPnaeS(v6YKu7U=K{X&=`5IbLllmMew!O8lkYZP~Ar=^Pu>;j32QS5LLT)KXtaz^1Y)Z(bQ&jA`tq{=hi<6b}!ZfaJ5Dhr{#VCRQT<$)!ch^%hJ!&nCUx+3wh$LZx z>!g37elQY8Er>ch?Z;->Iv(rAVMZKl1}S0MB6ZTXFZK`MzMEyd846xwUC-ftdMhR; zeB`nAyDR&i*?Nhs$0cB_Ag%^!_(I1IDNfLsd#xXA7Ga}gEu7#>eel%17r6|j);W{y*1o< z;j`09Z433Gs}n)DB6Xr9hz%2CvCnSDc_;<7LvOL5n@WS1i9C04xgD;d6TOq+# zU^TXH#EBo-j#Y1-aE^%{UMo_EJ&&%`mxFjyWWuy#R`+%vO>AuZdSDXvY(^vIsdHRq#h}a1 zuhBn2?p4`LplGM!@9c5BWG1rGwlK^(n)uLcO-;^R`=Ozh`}FS+bG9|d8j^C5bE)l# zpMMnn4S?nf05Kks?n2GybH7_}e}K93XSrUz!a>yuCpnnI7O2v7zk6~X&~|8<1K5ul zaw_zIN;2Rsfd9DuE13RY8wwFFVYGk$gxA^o6RRP7EVAeoAtBs4uu2^`{AS!|z!iqL z1tv{D>~g$r;$7H+SqlASTbdlvAwHuHxx3?;cjy~WY!n)U+*_Nc)2FZT76_-asjoMD zcV8%uQh4pkawVNDs}DhmKTu8PcCeqNWVjyeJ~APEgBCPZwfntC3>3Emkh##m3_tNq zhD2%t!TIQA{T%J3&ad6_2syJA*2d$-?mepVbS)6hUyzB3Sva8mj+tHk4~hM==xT6V z5xE7{^V;cns#tsvuFByFZqG3p(n}KR+i1U^VyENMZ>LAS?a26bMSMYldvPuw*^*;a zMJJl^D?VvvkVn@w3#W^b#=C8o5B^X`#gIt4vQNB0AbX1(-hjJ@pOm|W+qFVxN78?X z;HSJt0ccTPH~srY{cUsWr5?!X%n~5-_`S*9ta!)EEFgbS!;iH6-CyET({oOwz9e?Q z|1kB?1x(hwCXZ^yVx;RwL4SXbwc+UWJN(K(r9xHaAa|OiWxve%MBDJ`#Mn7im*AOB za>b!$Du>!UNF(V5k{{N8a$>!fJ_$_Bf#1jMs#kuJ}8LX8g3Z{(po*p!ql z_P0E2GFUIXKd_tP!LDy4sW&|h-;mTt%MKueqNc*I9wyJ0-A@UA+h_sey^VDVrHS#F z`FYJh;=XJ64`B|y()0>|qAF?mk&(!;Xn^5=t)$D|4)I+u!LQ7@s44@Ik2MspS2Frc zT~VRZtt5Gi1BB!>jSf3+WN!Lh@Lb)hy}Y0$XRxrc{Ief3S-L9%Kb$0xrD)%J5e9_E z(!0rb6%0S(#G1|O!MnRQv@q+L9*X6GbDzJjc_j$Zv?;<{DHQ3r6i~DLF!zouq+m${ z8+jbNrmKZo|DB)gWh1%rcp;RPGWoqH7z+hkQ_sl*+?2Zwyh)_L1N%sKVbj^|VVGhY6P>l)?_D^hN{Jtz3i&lGsX@2$c2+Vn`9;8mWkPs^}`<%K?65Nn}!Kh;pDcCiW} zH(2E;?hM<*Q>hu+R~g^&a~81$UaaUj6;<&MSVoZaSdeHjEm+6fArCjrZF`1h#nuTp zzV4wCxvK5aDY+AL;))-fc;L8}l^;7`J?mes$^H=iAs$hgv6MoEuDvJvI@a;;i}b$o z3G|rY1B5&t+z!qYa~_1YgikwvKD#30lk!_J=67#&%3=&AIQnq-hRyB^dGpSMC(|v6 zWz8Pdg~`#_V7K}_N&mcv05@2*fS#F89`1_%{xs>De$z7GFI`BY``_axH)1|h8{zE$ zc*Z6ZJYhmiEK*G?T#p^I8k5IkzJRR7pj_9eBG(^gRe8ze@nPWXcb=MwzmXzp=@T0o z1<)o93_p8sHa$!V5v>E4IyfmNVRlx`BgiIpuxdWoI^!IZ9U+YJhAdJOTxIbHaIC9m zF5h!Nh;jkB#K?j_5b%YDe#8uFr!YVD95PH5!~9HLFLh%i{$p}OxX3k7_vB~q_#}bl z2lXx|o_OWvBu=VjtsMHSkeDWLkhrj}hqe_L`+Q$P*@+&ix=4V$c%xjAwJuZEGN+ND zfq-JskpaQ0?clu8;lx$@>F}+5-IdQ0*a0c9-ksD1)vK*Id-&wOmsV36R)A?%=!!v$ zym%O*J|(Q7Ju?;?)JbG{DJW zmgKh?;`momPa1gijI7lG6uASiUY%mQJI2;$5_x`YYW6G~75KgQ<7ywFo0Sl`M{h6j zyasTcST=dz2#xZ|iz{oBR4mf-PEE4LFOpn3VNSXs z)yqOV+)&^LcI%XWoksaGgt5}*pV^|xlP340LRznQRbCYP&1QhQxsXKCOwY|YC)g4t zCWs7%3smpyg#8O|svk)BRj41EwXPde?s=SYkvq`k*?WihIDu29nGa^wp0wEudprnZ zEARbS^OUg3bC^}P+wRfHl1W`1jBUeLeyqgjSw451TPu9Ysc?~gRBcNpGSjx+^DD@N z_LB-sN&}M~g&1va34HdY#z0b%O=;(_HMV=MuoVV>ok&exLcK$y*3Rh%i(s9)v~jb@ z-0rP=Zs5Fi*~Cd3Y9=ae@N!}kexavD76-8KHNcD0{I4%96{e}PWy5mkf8E6Khy+Et zM?sl1wsQMQzzs1bW9cl8m_n0uVULqD;&?x+=vYrMxO^TXLb;J&J@bj`le5aJU;V0>&(Wa z^jB8%#5(dbrAXZ5fp>xQyOc*CL{ia_b5n5M+I&1c7bI}rH0iCA=r7QfN-cHUl9Lc4 z>7jr#(mi(joqBEKvn3ySg=twZ+{(=>N=IE7JB;c)ugQw2nj-3p{7 zuY1cGK3HE{MJ-7PV@I~OBJQ$VM8E_*WOlUoArSB7stCWe-d~1=6D`)rOLkMD0+lA~ z!xdwxH+y+-(l7elM%V9be;5#^978S|$v=<%C=fTE_)YiP3*mz+DKCxu4h&AdY>aZY zR+J$1HsXZzSJtLZ8BdDXbPF5?yq2OMeSFq_LyKH9?WDntL@pjau7>neZ#GW4IZ-JV z+B30S^*QJ^UZPRcx|-j#iV%7s5i4*J8(aeSxA+Cptn^sHfeX=_2uZh+%AbDz$>EuZ zEuORkptE@Z!C+kc@o)5qgqu^wBPC-S@K>q8m}_Wtw~acNj#YH%G}n)F{jHRR2q|YU-hs#qcR9M?2&5BKp|rM0Mhf&G!Tj7?_G0 zdoh2O9%d~WUT5zVJv*-l-P9uUU02d^i+^R=C}NYHCU+mQzvvukQA86Z@UL}&V@n&2yOYX>4JUuzkEzjxo9n}2Xsu@ztGbjAj>@AN4Eln>v=H{Y*d|xIbbLA_ndISRZA96-lH^4UbFkJ=OshFuo17(B z#8Fq^wHfd87IsVBGFV_d+%8I-Kte>siZA}qNF1lj0 zCiLD_I$oG1sGNIivz93$e6-4Lj=Sk4Pe_U96}t^nAN#qdjoOwoq6Y$MPX&gm)|)~{ zFBZMLRTuRkhct`Q9bTe;RTLMZb~1zD&r{ynDBrY$#j2aucC7u=eT`Fg`^Oe?kh5p; zFD$vDeC#fG~kbnBNV4Sv9>*ZC77)P#`e}DuMWO!MWJ* zYF$Q@0)Vppt_N*n)8ufRDz@?NZseCGaFZO7Dv}?e=D9MZm)7*{I#`C@1aWOM3odX- zt?DakW8$#SRa*DGPvV?T)PDkUO|h=@FZXp{N_wGqE^lqQD(^gp^unH2NhhVO;YKMNUC)_M>O?ZTEvGe)k}=poNe=ITgaIh{ZuTr=-3KPdi%Yo1WBuVN(J?Ii!77!=t^QXJ$4yyN9qX|;2{d})jR8kH*kH$zl(CQCYw$=!j4NJf~b*F zjwZ$}yLO0Oull^^mD+n62smpY)ysr`cF*}5RBuz$4M0HRI5Rui_gw0RSmK_>$Aa37 zMIO=?(#&2wbF>JmpH{Fnw3N5m%9yy}9I3cg#SjZn_!Hi>y>To8e@&f*(RmBOx8K}5 z(K;NaDWdYj^$~M*y8u&RW0fDa9p6CVSN^9hL()|NJ7KHXJifWq1|6pixDA#Rxh4TSLDn%!;-ljx9_K)SO2B<*N|LK&>ZqDaL(qMff}>m!DYt_zx*az zbPY#%wxl~!I<8m<{Mz5^p(@&VVxlEozguRCj`G*J-i?n(J}_jl02ZnN?`3Dy-42US zzzdzAOZx_+gY^Y!i7c<)>wzp*T1C}--K+%mjcyQmOTt@BK9IK_Rzi{))RZuz(tY0T z$1G>BaB2e$Oq|YY zYN3vAZwn8aTMV?|0XM31+>V6qt!4;O_=?qmGX~*>#_Q9flJ>L1CF+LLJg?@WckhTR zYE7A2%b3}OY;UBcv{2PEk=9h~O40Iee!*=c8bRJ=hmbhpe?l_*&RL`ii}A*V*{&0X z7&a-ScPQ6c=)0h-$_ZG>==)QiGi)^DRkS)|H_HhUmFR6(x<0VPnyZ`bbpL(#4Zul4 z@4b=lr*L_2)KF1Bj`9khT12hikauM!H0-`YG*8d>HRyRL*|5Zk=8@ip|8$ z>T|Txb@4soCVm1kuqz>iNl`f)usjDa-v$tXD!jsxAxlNw_}QA(>2T$2g=WUzHRd_D zY~YE=pFwr>ds9JUqvTn<(MWe9MjN%oNMW|`0l4NJIO4nN01THnLRsIxi=`;H|DGF( z6^2Xc#|lQI;bhFvdEX{P6g4@NEWOih@K4$7JF zK$ve-no(D+a(J)ud#wG~{PD5TcLJ;_!j`@QC?4mw0?_l%H*$D$6ICK~J=TEgf+^r! zKLKQ~u1W$)tqv_i;BZFaci&G#yi*Dd z!eF5|Q^rD7I|jN#2FPh`AW_!fIheQor9L{_-~G|h!vkvkV4?BRhaS3MA)kmTh0rpf zI-|qX5lFm|-zYZUERF((bEp8^Boj$7d7w0O18xnEg8PUEA7}^~w6|BnueMTNOmPjL zm{QH(v6#Ed_qDL(Z(%k5OytV@eiw@eN|ZYf0=tJR z>@rkuqXBBSLq_g9|ExbDgpYDQwg6oO@b8?X`Gs!N(20LN^#a?9x^-e0y4<0D-6yS3 zL9yFI>B+P0=GRWXUn5j(swZB;lg*XqknN2Z5oQ6RG+{5BuBUb}KkmX%zur5zokli( zE8~eg*8n#^D45FwmWWgZ)Lg!J4H;k#A0;6e##vqSCO#yW~;*y3!`@hy` zJF0e_krwm&Yuv0YVRB6peYMSN=4nRl+9Z3~NjTydROU5veoj2Ewq@;SI=I+y_mJ!w z{)6GJ)w>}I|K1~@Mqc- zD%}?j`cNMSpiC^r_Ej4>M*Oz+NZdR~=hZacaaYzMYphMVGdF40Lj<<+g|Dz$TX zmS-gfv6t7iC14dsFx3arO?xgg$|@g(<}lSfzB1L6o3&l22x7742@0n|tHbo$=X(7t@78dunWffR<@AXtJSQr2=X)f#4nY!l@v zpN!vc{AX=z$*Wn2Ij8LPK0B}X^?D`aiT1ws>+n*dBvhgojrx$fl>{{(>b!?Pu=F7fCh zz2ntdj2Gf5QQJ=k=g;bD&h5G+eYo13_%(zJ3Ufb)F{0;vG(8X=F;7pzo&#G~ZfagV z_Rj)Jn#MDjAwSqQ%rMQ|73d%myqG)=3-!iHju^f4+-M1sO8XQ-BM1YWXMk&;k1fMv zsZ_+EG7+DpNZ+tQY-v2qllee)*{N&fZ{A_2xB$)@UoK z+g?rj3Re>%0wfCGNAD#dUpytO@b0=*PU=Cga#Wz)7WnC}X*Js-&x{>rSo>tXstD&1+ES^%iJb z9nbTXC4^ThJ^YfwTxv2%^{#83`HMf0RaDKwwVQT8CJ{1763)=N<9e?(vO<(+E3+|R_IzF?Eqd4ibGd1NbQlJZY#_$3%C_ux010xlGcn)|Ky^Ugp85Cq32ud4dY?J^)m#T=&h=`0dX%QHt6X{Ze(i8-Alp;tI>0JV$ z21T0m-V%s_bVBHXgd}G_SjJ!ZpZ7iQb)7HgI)3pAft3C1y`Hu1b>H{m6HzLm%v%P0 zS}yyzeb$X%WJWrUmvUL&Kwx-7Lq@bMP0vu-!$N)XeaP-b^@D!8c8Tvto~XYwLLBwC z$~Bk{z2`K@96VLdV;of#o98zb6fN(ZK3;0}LC}g;*(iN%ZM`R3$74<_eoT1MhPQ|_ z)%%kH>%fZ4gE3_`ev{x_vqwzw#uEM2v#}wKlws9|l2`TQp2N67@?=NB&&zdFJE)W< zx(n}|2ngTZXNShCff0eUv;XOSxjUlQ}icTuJ?SmgP&^1ICCpnF1q7Y%04b<|JI(wXgFEGm2iXYZl1o+s{Z;oVCirj z9bi4J(ZZ!4JTRWj!PQ(vDe@d5vGT0tAP2Dlj5N&h&Gx+9G$idgVo{Dz`I^Nr&q?jn zN@Qv|HoVllY)#3$i=)YNC?QRFD@Qd;Y4dfMN8y`-qDd#%Dpps(-B85o{vd3iT6Z(y z{m|W|9A>Wd`Pq(hGn=lQr1~||uuq;aC+4`h5p~6R2hgF`mzOGhiKOK0&VsGB$Q+-5 zZWy?Qr0UT10>nHfw-!Z?&cvXWu52fWc&Q((zNNQHUqAF2f$pPOZ8f;~oendOiEH@TF(G zsh3rIZ7ZJ)AQ5$bbVmCk8ioB`k1gAhI;Vf4R%B7+tojlmi9+R3xb{{mUgKP%Z{Z+w zj&e?Mhq7B<0ne#(1tc+CQbqBt;9^0azOBoMpbvQdG&v$ym5&N#)c#eSMzJ}{r81uK z=PjOS9quC?S@cV`J#DhN4(Y9)ZriJj>XLMXGwmQG;|x3ltF^QWzp?RJ3oOTq;j#wL zD_5D(pFd&WNY>6w;v#+=5p|BBi zxAt0Ae$~JI()P}w;!^>YQ_yJxD@Gw0_z*)G@b@_OI?GFv(YMJ*smPQ)4wY;9kZ0M7 z#mxJ9y!M1fmrC+=pGLSwJS7@|RjzeusJB$$eM6qxct*QoNKAI5jP@-IpMhsK-;uu^p~xU!ek6u=vw42a#2q)>?KYwwN#u7tN3Kx{WJbN zSmvfGoe{5j$my|7^6KQ;;B58k{ZX3cY2?B35`<%liEzVqM054+hMBExC$~N=)FyGG zb7(1cTzM%Oy+!JB%$wfGSZ~w3s`$v0NB6V|Aw2ylufY|@sObK2mh+1^&xX}pnp66Z z7+vJp(apD!xV+g|^&S?ZQhfT>oVusz%&iSv>~#>z&eVZ^63qLsE?yR@k(P2E^@zf zkYCjROo>5S4>v~h?n&HV1HZ^#4p{7&#xX|z4$($Y3uD>t9nApN^0}yK8;^;0duXt)GDMy2;nbFG$1#kC;(foz z@vmqtOH~o<&a?-ejNQCsotMo3##pIQyAZ__t@>bj7~8YXfoo7OOo=WYh%LLio$rH6 z3#bgBa^U*0(?DWdHw7r&*_i=UByEy@y~_k-^gN4~XsfdBC~t*;at@YRt0o7*!GRQ% zzr)E?^5g@{9^{tPP)&hpUm4zBupbeh|8xZ*1j=)1{(bX)%q9&RgL4YA?D~_aq@SZg^8z+@`^HB|>VbOI}5N7nCk1{ppG3_xwu4zv=m$NJoO-{l3P!D5JTZ1ne zSKXex#6-`YT~_VHRH4#|LqLs`)qGr)a1WbH7Qi(VOHiBlTzq+p=sRo!%_+#}^=K+< z$*vr;7n|4p`@n33tB}6M*I1)i;=fTG`LWC=?M?OyZCjEcj>&x#jwARpI$!-HhlK4T ziPv4o!&}y}+)uZ02I+IXcNRTAULE1MioY-&f3%{lQGc}czf!o+5m>BTFg*bE@R-bH z8K>nFJc71pEf!r#9)D-I80Xp=1UUS%M|G{KFQ&H6AqyT&HPS01)emBO27e)V3GK*7 zb{3t@jTU@>mx@{#8M>cW<$H~mrfSaKZJ)4;d`YL6@mAi^ppX%C0(x@RFk{v^=|%ER zLsoBmmf@DS_lEXR1|Nxb)8`{e%Ar9ewBtWPxno8o!1eWN&0ZfJ(mk$ zffNjI2>{ykwp%!(<>VpWw0?!|MIQaq;~1U(!*x>^`loi}S==nHsN-pmb6w{auRAsNFtBLKMzL-)GG#<##Wo68*Zd zlTdecN6+WFg7ptxr4@^_h z6{9;Jqo%WC>5TlzA3k@VWcRzTRlVXEY0Ibv`53(FJk$HA4w-YjlI z$7c%9wr7m};HJ3vM|`!l0yER_Io%|ln0mqb0qyAp-`Jnm<@me(_Q?UYg&NQssXdDr zWbRmo_%JhaO5GJmBr2l(r=BgKIDm8yrhpjKJr4L_-JkA&+wv>_i&EuAEt97lU7}oi z(At8ODL`3slR8!lk((2q{x8X5Z@Iemw1?GP`R6pzLH~`l^MftS-yg{`E-}93*5hZurA8}4;3A|oa}uvNP35qF zA5mf)4V^jL&c_SdiX%(&rM<6n#;L=8K0nPYyZ|ercD7ld?54tgZlyaqDYv3hy&;7Q z)7+=+xX0p}z>*GNnhs5? z&iSw8y1h1lUHCgANog`hXE z6(Uqw>t2{pbnCVDQUW+gtq2lQp&gF?q%Sw^7X+l zu%FlLuGv%gIOP_lfzr+Ndr96azL$P8A$E{^OUAf~5+lSTuO=GMSa)i zEq`21Yi+vDM6})7cmXYZE8hIZ3!J$g0H?FtL+;Pky^|>Jth{rPGV{0-CV}(732JC8 z|G`X*FXyX@A*lZ-?3Pxlb)8{wVY=QcMyq%p=%IjSzu{Cvl4pCcdt;9HRZ{YASQgiP zfrEQj#8&E(Y2bL`ch|^PXbsC+5Za(?95fF0Vk?KV z_&*P&+P*yO7Kc~RCpHoykU9{MB-ywPD44OB{Y>44(Bh|dLG)U8K!Clvo?>*f@DI@7 zB7U=kZsGA6^B==?0kp-|eu#0CE^LHYWY~b-x}qpx6t5nYwD4cGZtr36Ny*$zw>n~Q#9CI4Ga9sSzICV#!@z$x zwLM(>-C{w%{{24xrdWNOD(6edcRkpl1rkjVk)em}-yZ&lo)tWAxA5uP^Lr2XKKj4L zUG5DKmh`_J^Sy`PqSUuj|Bchjy>Ui6$@IHlKclVu`fHr|7RCN=H{XAFTRB;S<_x&x zsk7g`wk<2l53qM;*=IA^O(lyUxuV;5+r`#Sp&{~o6S$UzP&7dQ3U+>X%9pR=^d-sL zQx_`A@3gb_4L=Ht)2hYXqifIiuIq@$1$y>?X7fkdzN(=iLaDDn@-t7RrEcc~_)39< zKcg<-NUTz=x>j2b?E#TxYXNkwGl0am=M`0j`s00I<);l~#!a}NVdcTZ@#js99MWY- z+9);+wSQP+3(v;|MsnU?0zu;KOd4Q=>wz?3fJIG6*v;bO<`60f1sKp9BY6V9LxFMp z&(cMp5*r{XSD5Zk6#>yfDyGuW8EXI7niP%OT;muG*a3wc6Kqb^aJ;zqb7;N}{}Kq% z(rNIGy8jZhZCMriX}gPOVjaMV1|2o4o2A6&_&2|Y{i7NP0#AMDxWK6jTJ)m8@^5d)zhwO?x+1Ugw|LI+A!!Aa3Q&(%(uI#TqsqcVkY_<%GJp*$AV?67Wn?8=lld^!sy zlH@v3-FkX>ow3sJ=bFD_A9Khu=sp^_fCJ#m*%GavF?`4?Dmd;?>BT| z&V24~uu+ZO-fZhuqtrl zk(C2oWYAT#g#*7^HP(BZDpuhuTWx2T%nnut7Tr6*l=$5}P5KeN{p$_xYp~pVnrXQI+m5mbY`=wu&T{Rv$at~$yvflcS4y+GME9aX zch`SxM&k(V08=+aebaG$$a8bgtuR#;i1wp{E10?&|9tw-cfFziG502`D4iwV8%{Gj zTv6?;_^TOhJg6<>IlpPSEFX0f*P1b#M^GtEp`9#2SkX!l&@TOF*9H!*-*>ag5Kr;{ zz4CJPs8@XpFx|M*evX+bsQvl*=~NyNAcd4mrw#1h^~!wK<{uFSDi)xqsof}}zzxS~ zpb(lbHB`N!N7whz7i5tJT#s(vNs)2*+k=VGt@w8rt>Nyn;65pBmrGWW1;Ur&A8LG3 zBsFZQ)5o{q`%P0fHMntcKg?A__RX4aXHuc-04^kyEdL428HL?&S}6UQ!M2zx@KWeF z0{)G>GIlp-VwnMNkzy5%S{Ej|%iG zAp}2#fLoy8w?*_|PTnql@ok?4@+U|*8(sJdBu+mup^Lu8aCpEKk?-6cfbqivU~&S$ zpSIH=k|%-8{>!dYV^?08TaaFK21yN(^q+Bs3552~jtRDBpu7%*Dk${`m=LgSM^_SC7VS2=V$~~ zRhv(~~BmG^An#Owf;IAMl(=`j-E=iH3DTj@#V(NmwS8uqexLVO9fYH4EH0kmt|3NVo3 zW~V(Y1Y|^NpZzbyjL;W45-?~}d!5gkqA{z-5%)tNjnn=>E-&THdF3uYF+mA%v0CQDNwc?cj z_AJ>Gt;^CQD_H-LcMfi<%j%}d=6wvq5(<9Y7e1gAivC5SJd39_xf zJH3ewljQ{b&AgY&5EMmZv8>L19{I~w>Z(xh2~DEu!7|m_^;OI2Vezf#sfJZcYIZ`c zW#?3*Jm?H4Oo-nRV2!p z>A=K)o{<~zvsjhxeNBmwBt2N&v_Y&151 z%HE~t%@ds1uHD4KWPA^^T$9;{cdm|do_~oI7nI*>>9fvSLf~Tsrozi~U~Wt&tJgv| zVbQ^!Tj2txactF}M%@=*W!Sx28-Td2@$YQ@sfEtHy!&=b<98FM(kEGS(L8G*t*-{^ zAwz*-mHh+j0gM|x4+P0?I-Iz2Z*HqTYxZ1vhI!J&Ny#9vGxwJ6S-@&YvbO3NiuV{7uI060(7Vq zKu;RMI5We@eAYX3hk#i|KC$Ut#<6LM^UGb(=9UrVyWo7SWZ8xc7sgmhy!ht;{`_hU zQc{ZvJLfrZUearCQr$1K^0;+uPo_n)3mbqxIi6;(*PKiaRgQ>=YLwOAxmVIvR~yjv z%11V0m4JQi`Eo9W=c3EFO8o?+WVJNi9EX}LQC7HG3?UOJX~RD*l$4rsyrgb~nx5c& zH7T!X`9J~|xb=)Wh!k$#ZO(@bH&l=(H=i!Hipka`3gpnpjOpq^2K8fc60iheBo$rY zv%UTg?{+xkzw>VQbql}BP}d_}nd41!hvHc;=vj*zYwWHmGjlF79WG^msVL&VpS31dkmCx=|cR}x3S6#j-PAbfQHCB4+{`7ROkFvtx z<58FoMH{XC&>n|Uq`Y-sa#oCW7)qKtJ;b%XK(WQFj3YWlo8nULUe+yW`zYy45gn*> zG`N}hJjfX+N0|=C;9Dn}T2&>AuvrE#)|(Ct8qP2sxzjA5Pi;CFggc&RuRLRz@0}Ts zd`#vqbMslorz>WTht|^oU|w9)D}|!eY!+P3-G@Y*aGM9D&&FzKMJPbYa@j8e2`@lS z#jW=$Mjd_sA-1yTJ*c6#o?5W!up8~lKOg+JTnB1yC zqOU)+>hML|z>Y@bjt!H5?ZnN(oDa=y7Z<%qrcbUX1XuyoypI~7AYw*)o8IUoDC}$% zP9*HCn_PgKZ;hx9@~h`}4PYkvh8UGbQJc~E`N{&ow0xW&$0k05QLf65KOlV^oOp@3 zT{`VqFP>fdJbaYP-_J@3017ZGreWU6$<)oYLzhZptV8D6olQ*9*IK9zVSfwIcWN7% zp9|KHFA#gyRg915YuN7gDe`Nvi<=O%v9X|&EmC26vURv8Aa|1@y_-~b+FvSQ1 zmc6g`#Iw_?tQpp(id~$ToV;UpLgv#UyVZqJHyOZq*U;Z*9P&BoEv$Lhn36Dd0+^7j zT6_Wm?;E0;cYPaQHiK4rymW)cMJO)MS0jBbnnTn}E6&X^4-tJweA$+4?-!GXjbj#q zfE7bgt#zGyPZjMA{*+)Yvd*gwNDuM+izwfwPiV+i#Vo=QmbMi7^4{Hof{Vczz<0NS z!)G)}%9(RFsp*yMoNdTauUYr?^O`W413RBwCW}K+j^1o&b|H=8a0Z53l6U;Q1YSRy z<4e+8O7x%1hHc}`=HCk2I&8|h4x1ukD5q0UJwoRM!t||_sHtwAqZu%zu?(2J zulO_J!XxCX8r$7<+z*b`9jv`JMOAg__OkWEM=L$YDJpMzLIt<>d@OS9!Or_jvTMP2 z1`GLA0C9g(=90mpMT$D!G{d+4T^W6|@|0YzW4cWJBSXBA-b|>bVNuZ;Hj>I+@~a`I z;J4x_H*gGWhO)yBlm53v5uMH4#uWL^$vTMZD39yAP4+Au8fjNL-SuKOUBV|ZxlHWd z)cvwB@RjRky5w;^@iC zjZ0$!im%c;E(!IRPk50dfO1+Q|ielwQ|<1xnXbYux=gFCNu4 zySjJ+NAF++y#ls7k!D#91lxDhr!UEu*Ss|{-4HGJZYDEcat-h~T)s8t11w-P@`C+U ze5ck&MfHMk70RRM^-O;KB+ELGV@^BNeZ~J%l_hOlkxk^mrzd$q1ih`^qm^ctz&A+B z>{>MAdBS_7`Ottp@nmdf(v|*t{KBEZH-3_3L0jc zg)UYn%vDG8m72J`dn3Ak#LuPF$3?Of%2?79;ShA}os+1c#$6uRA8oi#$H>fC{5Ll0BO{Xar-}6~f;`S4PpDI&@&;wO za=A!?oSmf$c!TuNeqiM{~7PVoGl10A)yfO>6_!npQ+x=!hCnEPZ=-7_{u6U-M) z3yo!+O^WMPWw<%hP3m`@^9b$ zQn+P&2K3_S+3ouGA&b3@JOEMeft0zAj*)>gQkECrg+gvG4QuE1VLHAm!(uVOz~nK1 z(jeX+>2n9yb2Luiciig~2C2ZVg$@0z%=Idtv1RoKz2`Az1JM zZkF!>76AKs3`k(I1f4<83eGX-T;^zJy!)XG`DU6g*(|2F5_lG9cr5*WTDwHa>dI9` z6fvcb)j;$QcE4gzs+#x#X)sUhOP>=^&4JHi^e$=FJfz}Gd{&%A? zk~TIMY70kMK{sG=k?{UY!$&&n{8aO645`lH!W|4>n@so1J*exmVc#A+%H1AZ`S$kH z_jr=u?BA~1R=z5dqGQ!#3$8i7P^XahBIAqf0&3Yw#BUnLFOnt)%Sgdbr?V>|i>g%E ztBgx%!|dFm7Uj)Jf24JT~*&FJBviOlr7?$H;_e6$$^%3U#zWD)Dni&(`~r z>0v1U2mi!~&opaqJZww-JpL{n8ks63ZgkrbR>8O;cwP>!bI&xPtk|%lGyJryqNpK(B2KvtQ&FS9tq%B&G-Q2^1wv5ds zj2&5V7K7Azf92@;xWUA&a8kxV8*qE<8WNy(#Ot>IsJa_Q$|%dL8YhV%e0)#-w!1^N zQKibPRX@_|ZJUh-BMZiXl;kNq!PB7fAkAj4=^Fz%f;ysMO4S<1<#(-t<=By5zo1P} zDtlXEv8WZl>$O@dr}Vs#O36q2_2jO_CQw>U6PiDF3jZu<523q{D$HhBkwywlNACeA zm2(hs&oun&mfr_BfSoAOeEJ6~n4qauP%9T1T*V}DckfzkRP!!i*Ye-D%79rEd-q>% ziE4hOascW<3`OWd|GzW`@jEc+|Ixbya_t4>Vy!}L8-$y0$!^Kw%+GBpv?;vh2}leN zUTn@roK`eqS0~>7yJ{7!#8unvh2OgZyNJ>vZ5U(qsjK$-!_+_3Mux>_#D!Ma3CjTzX#V~D&L#c4-*UpC#%&qcP_DxJ+_Ek(L}Gnz zp=>&PW&s3>`mrlF^>Sr{$TU|27nR8UbAI%q?RUWUQbVh)tQOY%X!g$bphDA_vv%rEu0+<~qQn$45x+Z8I=^!Mt~uyq=SN58%FfM>QCVRdfJk_|1l_cf&N z>+1~US{tgAt-kvRlKXk-kZ69XG;Rh|sI^5ZmE>~87aH}U(mttG>^x6b)V9$Xsjji^ zGum_~?#yf7;~6M*DXjBfZ0n6^j)V_+iU}wZ3_WM3M8bFY)5AE|9m%?7)6_UX@K*EP z+g%dbpUMxMHFLG8%yi3pAWCU%`We$$?qVW}0>%+-V)hG21~4Rv!Q{hg-PUEj!>{6p zz2Uk=xlKxY8jsI&Qzlk0%udlauN4JCLrXy^9_zZ!+d3^fW5NvU>T+aNSZvuIa(k5%+tglub39}+fl5MzY-Ef%Xqf3KOzD5p0(Fj4U>V(S-V z>s19~ST+%O*PKcv+ND-Y#$bg2ZqqK53Rww)(qo9Zc&O9l@9Q*@VjpQaXA>1^KOS#c zZ92jegC%VPwb{c29tY*7h9G;%DDs{u}W*JDwOC*v%RM9yRy3}(ek#O z@}I0t?`5o+s;T8=xdW&QO8Mj|i@es^Q$Foij3|5Otnx=$fEHpR0yhxInmlf~-yHKs z*ZY$wvK$=JsMQ&7zG$gsk!7i{rp?g0R8N7*xRsUy#Etg*@Alkgna1R8@een~Ftrji zz~}D0IOU-K#IP&x&{cwTS7VVMv4yYH%$iO?-IAoY zk_3cjNXquJmNZZooPsPePsP{P{F%hF#iuAr+j{(=(S2h)y^rjCOD{j#3U~wt%sPer z{O+#a@)d60cXwNwqn)N6nAf@tUoVsJYO3F~SSIo3A8HUMc!a(BQT9Qf{PGY&s?yeb zeiK6U7z}-0#+(sP~g<=-nHc{$B8=o-En&olyt2^Rd2D_uuecdf7F7mRI-X zO}5ul@s-TZU@IXP41Q8`+dD>Ta@V13@hko;$6st#0uL)@HSB+YWw9hcPMF(|)9vpg z1{#Q=nLPYP$>Vf@8eDYH5qIU%uMiY=L-_X)8?lvZUOla&{_L+!pYm{)_Z+rJ=^7sf z+L&07eey zbG_YI@B&xZyy-(k;3=sC8Nj#_-?kKR%Qnq9QHu262J61>eZIPABK8Ro*@!1G9%nCo zOwLBebi-V(BQ9)xe6=Q*>xR6Ae$5h>r;OTHwZ}TTedCcidLsF(0ZiF0okSE^HZjO| z__U_Tzc{>n*3BN#7JU^b5%5>RX<&HY0h4mj^GH<3LrB{xTc`eTK|r+-Ty|S(F`l~x zA&+g>N9rmH>KZjZ0J^ko#4%T%;DzUTc07+_S#LqL+N=GTs*bS2c*Aya`jpT-*1GKK z=(v1Mue~7VdJ7TO#Fj_P-vbf%u7}IAxLCZYf#(rs9;o*F^cYNkl&JU+!5qek>E|vA1Y-E*md`9{)JtguU1Cz|!9lm$Y!G z+wy|f6|sW>&Gh3JjKwZTgm7z8L!RIy^Z;;t9&x!K%T8~cYQpQZGyUm%p-!SHd68yE=ZU^%OOv${T27gfaD{=v+Q|oM* zRV;^dz9;6loI6&}eqA{=d#+=k_Lc{A_zXNdR^#3-UHuH0(3gG^{mk}PxMwVwTWIRS zv%Vg!T#+4EfXtHs5prz>CLM6(mP!~|do(@$Z`q|fT8m|J^iA<76BNBi3gZLk7;kFq zoE)C$hY<%k+M8s3qxj7qultYfY=>JWk73Y*>t5u@Y>C6hUEi9b?g8&#mnHo-t{F)2 zj47Zv9<)cnkU$rNw%qKSAF)Z%GO4@WCLI8LPdkoc$A)h$@23CSdRe5IZ! zTj8H4Mp8`UVv|jLA$1cPF&%p354*{R=QACpylr*9+db}EMWl1d>9!nCYbTk9I5|HE zC^?c|U3yUn$+G8%eeDO9{awDXeJ?WhCOD`=%oL`eCIbT9Afb3OLE3#$tnYdo|8*1W zLW~(4MdEzl8(*gcr=`$Bw`{2fCfC_(*P@R?iVlQGSi%5j6Su$Ol#t9A{2`;C?G8^4P& z)lKzGH`a_&_SqswMK>PEvJy2CL1KKk^c}DkajgAFN3YK#b=VQxwHy7xW6Z?0?i6!f zDnN)Du=CpIY1_@(C4M-anXFpIs8e1^Y9^_EJnHTg6LeqdniY&|G!zb&AiXxgim# zsAD!aNfV+Bvl_rad+xxL(AOd((p%zHaMf3}D%TWbf#Zvh+F4a?f2=3}*A?e~ z{Ko%Zf|ifEHzd1N z>A>|fPBvjuzTj$bDJe&PMZ?wZEURj`wA}888-O;@d+Bx=%&nY_26x)6Va8 zfFa9Fqd0Y(zK*g<`y!uoz~vGhkMJqSt0IGgoi5&|YYIlaae|Gza$X*V+{r4WryHP9 zwrjR1!{Kz5nwEygJViBgY%vmkiv{7UViB>x9RC}3Hb)l`MaTYEo;^V4v=9vbPGcHr z5+W}^=A_V+0K27!1%2~j(K;w)Yd;qg^r`K^#~Sln8X|q5OwXK9FTVyE&eoDwk}f>x zxAi)v60o#9?;xl0az?czb9fn2MM8w%`I<%kt3Y*Yp6@$tZq*BmCIFB2Tw5y|=p8)? z@F(|L@1Tg#({L_IYcDW*XGJ!W}VhsNTYM{^ZwQTFK?9oiuo z*IWQT{+s$KL(gm7*|}9~j8F?G!U)Hw&|!K|T-Ty)7;x^lGGlX9f81q^DHKT$9TdJ^ zdcf;sk8V<;_%>(3p;IkKoArbZN-4m#--uEqH?9wFT;IJW=})1kdO7m!buj@1u{~1D z8bNb?!UL?eLFY3(RjzaD8LC2R4CAQJk=yiKgr%C0H{{UP=z1>H}QO zSZ-Fz9}$K_=5ibh`yC(dbv`eitsiB%uC6zEC1w$tnsCNh4sArEU?K(8dX?2Np^w7ITIzoi56UzOS!2x9oi^zlKdz# z9EZ7P3eXC_+ei}0XKgYGtX``4=!95QU97O6+*+wcpB*}R&0N`n| zB6;rBD_K()9Oa{Ig9@y`ceg~_QGnmvz&F3d859!0{<3)uc73?os4(1q{0Uey3#W%a z4rTilc&!Cgzh>tz_tO2~3-wQ@jyauJ&=_#g>uxHqv{q-+Ww>^&YLq$R`2k?`hB>wf zZp?eRySlmjeZ<0Wyd^K4ICmfdSUTd5T|}x}dFi#}r9E~CcZwxyVRCrJOnkJ!l(k!G zFK{1DG6llxfs6OnFDkx9U}sY;U%u}X^5hxl`BTuj>%N2kIqIJ140NDzxZre>+694j0x?-;PCe%Z$p^_+28df?{E7 zyNQkG&x6$r*Y_zAQ!no|MmAEGy5D#?>CFUeMY~0uZz^$a?>7EDMZ_t6Qcge!(Vwqk z8pXxlbLLd%Y0NXGxzF;ABbOAEItsX4BSM~?1;#RCBc6#zF$W*!j*s61V@DK)@72kt z55D7J*g;K4`>BN0fe{$=xv+qiX2bojQu}tGqt!W1}VkaWp$x4B;BAd%y zXh`^bU#j@tjpfLNbj&S*Vtwi-ETngLSyuF&I?xueIRPvl26Y9i$y>Oe*YCWsbSg-Y zPa%a~zIPHP&1!>CDPlpSZ`LQW6_z=*IB`QowEH?UyBKKT@~#+AHw>n8KjH~n)768q zJRby|0l+tSxJTH+>eEz1W6Pv`k8_%^&-RsWp4l}}dgp^ePLFG#4A|4Sfle?wjWsTk z&%l9LvX;|SAkCEf<%9M}$zrZ;Lj!d}-i-sEmKPe)LOg1zFxX6Vd0Kjm=8~S}RLZUT zhU?d+$|mn*HxIFwoeScDTz&f1oX%`IHcB^Gb=($1o~V!6Cx$51LQ@8CKEllJ3DwrR zB@8d;!p+74uh!=-08k$AbvHZxQp8-q%iq}!s|t9Ha|JVywXIIHN*(@ zc6;m2R}I$Jx_IVu%WO1cY;VqB>K~VZB_M`_E5-L3aliL$XS|`_TBvPC zx8aV;D{Xb>wkIT^{gbwfYJ@K}Zn?;R>EuKfs=~p%7^c)?Fq5`|;~X>AJm; zOy^Y-zpNEvTXZ8v#5H=vso8P|=qhi%(7JgOk~;!j(ocfRbprmkDGM%P?guNo;a@(x zk{~?j{^#mAcI!jB`MCz`8=q;;-MyYCDzz0JY<;dQ|E=p~JouGCOz9y;$2frZ7=^@+ zwzu*IRe-DzJWPQeic}htLB9x;&)_GJ=@0Z1ulZ+PKf8ge?Fo6?$c{ovSiN@v&=@T! zRex;7zl?Zu2Fh@}^jfiylMT*#6O-cpA&GAQy;A|OdYq-%waCi^{DMWoSN^C~7N#`NCKL zwLWGZlABHW;d3Jk(0sKW2GDT2)H1MD0s~fu0CfOj#Afm-3i?|$)k`xT$?PTAUWBcB zOWK~b133}EJea)+1M2}cyNz(WhVDp4-zSKO%6m3~8ZiyT!#4}}-FCZ&_9HMeQLcmC zv@vpVO7rzz?@6G1u|=A+dN#sEZwfm_MFDSu%ebIpF%>O_ zRi%V2aFG1bDWZ?FFCa01KC;;MrB@lKZNL3wG)2IMx6DmfnJ3NJ`Q5RC6HK;FpJiEU zpjEz~iRKJ!4FG%tTwtZT?zxQmw|7rovI8Rs60wk(vaF!7R4|9h5CuQJ-mu^fW~hZ< z9aqI;@{NXWwhbwnEy0d69nksTZ7WO2L&MR+!$)mP?~a_O#yQ;NNWD($Ot}DeHi*F} z&;P9$0k|?6+f*u9M|eNpwyQe^&m%V~7o5EknOrGoEPFWvX;6DKa1%oBw)$V1^znG& z^V*oa`hiX~308|Wy*mF2qpjm0OzPXbPNnxtyN{vR7e)&8Z!?u+V%FXr0&F}SMHCRLN27)|T52u|-X2&=vt>g{^y!fjrKAX#p z@|5MKLp`VPM=6XACLB_ysHNAK5f|Rd43E8+%nj@gGY&f18DOZ*2-F z=Ca(~m!NyF#7vu~N?E5^;j1_Z0v>~Ip$xx>DV*K@e8HMz=1Rfzo`+%cOdn_ir$ca7 z6EzC^{ikn*fs>tpd!6&_t4NjUz@4F>=2)S?nXjVDz2Nbk6!DHu(dJI*ozGF@c6Z`; z^0m*cb8a;^t^y#o0{^<@zz`TFNK;683y^p~W@54pc$WD^M%Nwf`j84~x9X~V|ET1G zp7i{tHcS&>ae*Q^x9wMME|`|b+rtKp|CIKeoS6QTB$kZ2Nohv;IZy`0BC3ww#qd?> zgP~re=uw4Q-_~tcyIM%u;P22>?|ME%H^#rdnvHMhZXL1^8W$@vMkG(EDx1TV5ldcR z{LOQ%MW>~JxUp3u%4$`P2+|m%lTMrTj`XiyTkvn%pazW5M6K%L7aCRMJlE+fxwV>E zkk|xXfGMFihB1#3y&8g_Dvu-kpKPYgH>xl{<}rsCz^ER8gqlaQOi_q1jMM7!dOK`E z!xDnp1_6lzMui+H!KWOyfrK}`>)PDPXad;;8YR=aPONgSTcBPss3Vkv*;Tv)4b&^? zwAcdgGhzrikBn+sRiAB2aS3%_@%$c&Nrz)McKg~+8-Ktq(w!ZzNZomUV7LJYmohHI zb=ZHWw%0-hSEAgS68mh50#b2IISZimcsj|YzZ0M%95d!CVPQZ`REqel!W=0o@f7JrFs+X6Se-CI`F;P#L!)Yb56`p%FN}ZPm!C~0GF0pFyP6KWLPfgSJdD(e$$nUj zmW=X_dQFeO8jThm!d$)6d}DX2s7Eza*0U~>);yF+*R({?C3zTu%U75B<^&eOCqmTU zr_geXQih9kw>hXZ0Gzna?^KNziCeTaEn_4tdNbK-E$f!+-^$h6QbR3n(*id4sUt5n z9t7bR)E=_9b$C;W$}9aAP~iU8Qbe5 zo(Q!F0}VDltHTN|6aZ6-eRRgwvdop%#hL@#_iNkV1i~cREBVJp;E(yQqF?3h%1WAKQXr`Py;C+TeDjDn5l)`9Xn_ZUhfw^nOui{*`t zBjD^aiHStr3Vd^X<~Lz4Khn-hG8Gf7>TPK_3IaoJE^4!0Zy!2}kEcB2$5yTQwrpNy znYDgkk)K*cG2G1fk?9;@c~2RDX^5?T)qQNx>q*=Su6%4#YeH_xNt-;u#FQO+zauDT zzb#+ekZGduIdKc;Gs*W>Z}%MHskWHHj~XGU-E~=p>Lp(92}|~y8Aw+)RTv0Ymg2tyl*pN{l0_F2Z}q1btJE1WR>Qbp zP!1P}Um7k}*1ut1k3T{qHW#sJ&Ggrc*ZCT3e^{35b!H(u;cq=w+-|pGxRtYdk<*S( zG>Q0L@|xXvl_wXab8oWozyvn&U=hejLpF=dCS)}q{f)D^4PQlf_F;tf;uFs?fhQdl=+?~brk{g!kF<-Jb{i5`;`z0iY$j8bmko|!%~3}mWqqastDOYSoCj+Oo|MOWeQ#N3d1bHA zovVGF=FEKjjU&gBle$7Z*vDfGz>4stplI$``SfWKc;$!B1%tzB>{(M z^O&59B`~IV`)Q}GOI(YS>BgB1Hn$Mq&%kuE2!Ifuulp9b?%Im}S8}z4fE5+iWk}-y zzK}o7W}(tCVzTZbP=k5(--natP{L&V-D)1-o-xqrL84D z*?ixXLiB#7KtJX6PfaV8UE{|6jFlkN4QspVn z5U4PCE2WH`{e zq+HD%*m%Ae-nt`W~(f%rbTa&+kMWr$}7qi%6yl2 zY5<`GP?^*!9^6ht+a;}Upe->T#ljitXq}?QtD}Uh!R{DX7fXs$$U`LrH^%hE&0~K* zzMz8iIW8=lRF;2koYMMN=nq6ReuPaes|s$obP`Kq2M8ST#wA4KJ-gp^7c5N8!w&{` z4jGVTmDTCP+E4;1hN$<(yQniikkGSdqP4oR5h*O$GceD!xz z_EZh2e<|ZQpj#5iVQ?JV)3m1gDEvhAfoc@Ob3wW66R+f=&eM=iZ|^;bSns|vEL8uy z?dXX(^1l$e!`7E$D`E720-~YCA#L{=uPeEZt%@YdpQYnmf4UxkW+BC7j+=TkI@)}( z2NN)F_V$`x=Jz*%jv=I$IDP`=0YFqYQI87}zE04F72U9B;#}P}(9e*9R=$t85pj9* z(p_D8q_G6(6|@#dTeIxemd!7x0`Wlri2{WDg&1QEL@ugW-Q8C_^bIN`Q9eJIm9eJw zhtmEOE-D21Q%w(6hE`JdJ!-TUDjkdWL)wE`mjEKVWC`zy`1`Sp85Oy=t&83a$}#x0 zf2|@v&2iInC!&7Fh`i#V_xXb)SPV|@?6%uo4OB65o%pxcy=<;eLTvR)N< zUU)C`I*RtU00A=kUN09Z?3>pl#(jd0OQg^EzTdR;E<%Bj0olua)v!zh(R|m$UVh*c zB0%s~y<7`=yyDK&hg(`)46fO;{mXj8N1a+!HiFwFT8A&5NPi7wSkc$SWiI*WL7l7b z)e`Z#no0ZoO&fjZ7Q2CD+X$PP_ru)q?e6^}rySG*eU&y!a@m&#cA4RO8liL>g)J`C zaomwus!&jnx&jm8heIrTrhaFZ)@RIr+H9f<+-Cg+CVpPj$M8`InwPyW2V&}&)=2*nIA?F3ptP!GtUJ>Tl)!7~!S(n7HJ=IG^zvsT(p^Q}e~r zh1dHfH+F92o4hK;R~gEm9|*ju%`&p5`q-ZE;J9JcnxW!TcWpHUXHDyQZpJa#*YP=6 zo#6<>9D(0n^=9w&W_HIA;DiaM7%!lgY>8H@o)JwBS($+d#Xod%kvb7`(x}3>Ix@}w zLD-41RvHM0bBq{KI#@KHuJ(JEYF$Zl-!%<|w)P7^@&Swq*v zH(tBG38C`$MM`b?&9-<1pWKCyoa@Oe=N`8jJyl~+F`<1~nQuG*Y|t!g2#rji>Zb8p z{DPFw&JT&j`0k<$+o!r>9n{+;`p&esQDf<|QGvil8_h`}{L!ogwBDOBeL>XEwVWR> zG(w692?YeLB=4xrO)gH^k7{X5h(l8zCLWg<V@*t1uhf8UA8xg4l^0*=}h~rY~o?LhO*%ddBh1 zJ0;Q8$T-HNsjHb!S9cNP`>PYK)okE2OuLKLu+VE2T}My$%t&rHqf_61RJLH~oRONU z)&Xnm$MN4^T_$0^vdgWn57gvxJ1pa2#$Jlr`ehP9qT0gDp Date: Mon, 29 Oct 2018 22:20:24 +0800 Subject: [PATCH 09/10] Fix sequence diagram not displaying --- docs/DeveloperGuide.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 571d110bd690..46ea85c23d52 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -444,6 +444,7 @@ Step 7: The model is updated and committed as in Step 3, and the event page is a `TreeSet` is used when retrieving the attendance for display 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 From 995755f2526321b72dcc998d26df6b831ffea64c Mon Sep 17 00:00:00 2001 From: chiaxr Date: Mon, 29 Oct 2018 22:41:11 +0800 Subject: [PATCH 10/10] Added PPP --- docs/DeveloperGuide.adoc | 4 +-- docs/UserGuide.adoc | 2 ++ docs/team/chiaxr.adoc | 53 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 docs/team/chiaxr.adoc diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 46ea85c23d52..0c7bec1d1805 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -441,7 +441,7 @@ Step 6: The `unregister` command command tries to remove the username from the c 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 for easy sorting of attendee usernames. Usernames are sorted in case-insensitive order. +`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: @@ -474,7 +474,7 @@ image::registerSD.png[width="800"] ==== Future Improvements ===== Adding `attending` command. -* Allows users to view events they have registered for. +* Allows users to view all events they have registered for. // end::rsvp[] // tag::dataencryption[] diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index e1df7c9ea9a6..011ff0561784 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -257,6 +257,7 @@ 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: Registers for an event, adding current user's username to attendance list. + @@ -284,6 +285,7 @@ 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` diff --git a/docs/team/chiaxr.adoc b/docs/team/chiaxr.adoc new file mode 100644 index 000000000000..a6e74dbe7d25 --- /dev/null +++ b/docs/team/chiaxr.adoc @@ -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] +