- Install Instructions
- Instructor Feedback
- Important Detail
- Entities and Noun
- Feature List
- Design Patterns
- Development Team (group_0238)
This project is the final project of University Of Toronto CSC207 Fall 2020.
The program is developed with the intent of helping to solve a series of problems and situations people may encounter during event management.
In the project many tools has used to have an overview of schedule for various events, and to allow people including Organizers, Speakers, and Attendees at a conference to communicate with each other.
This Project consist of two phases.
-
Functionalities work
-
Great understanding of abstraction and encapsulation, but keep in mind that simplicity is also important! There could be a way to implement some functionalities in a simpler way without having to implement many more classes.
-
Controllers are also printing to the UI, and since you have presenters you should exclusively leave the interaction with the UI to the presenter classes.
-
You have a package named UI with files that prints to the actual UI, and also a presenter package. The Presenter is the part of the code responsible for sending visual information to the User Interface (UI). If you have a Graphic User Interface (GUI), the presenter might send information such as which colour scheme or theme the user prefers. However, for Phase 1, the only information we display to the user is text. For Phase 1, then, it makes sense to have the presenter print the Strings directly to the screen. So possibly reconsider the roles of your files.
Phase1 Mark : 9 / 10
- Your project makes good use of:
- Design patterns such as factory, façade and builder
- inheritance and interfaces
- packages
- Someone using your program will see:
- Easy-to-use graphic UI
- Speaker Statistics
- Reward and Requirement point system
- Search filters for events
- VIP user options
- Friend recommendation system
- Good next Steps include:
- It was a good idea to break up the Event class, since it was getting quite large. However, I don't see the need to distinguish between an event with 0, 1, or more speakers. In general, the people who write specifications tend to know how they want their program to be used, but not necessarily how to program. It is up to you to decide which nouns should be their own classes or not. Can you think of a design that would simplify the methods required by Event without using inheritance in this particular way?
- Provide javadoc for every class/method/variable that is not private.
Overall, you were able to solve a number of problems in your design. How you solved them was sometimes a bit more complicated than it needed to be. Can you think of ways that you could make your program more streamlined and less complicated with the same functionality?
Final Mark : 17.2 / 20
The UML Class Diagram is located in design folder.
The list of feature we implemented are located below in the Feature List section.
The list of design pattern employed are located below in the Design Patterns section.
After the program finishes, the session is serialized and stored at session/Session.ser.
Notice that there is a demo session at
session/Session_demo.ser, that is used during the demonstration video. If you want to have a look yourself, on line 17 ofConferenceSystemchangeSESSION_PATHto"./session/Session_demo.ser".
Every time the program starts, it tries to restore the session by deserializes the Session.ser. For any reason, if the program failed to find such file, it will automatically load a sample session, which contains the following account to save you time when trying out features:
| Type | Username | Password |
|---|---|---|
| Organizer | org1 | 1 |
| Organizer | org2 | 2 |
| Speaker | spk1 | 1 |
| Speaker | spk2 | 2 |
| Speaker | spk3 | 3 |
| Attendee | att1 | 1 |
| Attendee | att2 | 2 |
| Attendee | att3 | 3 |
| Attendee | att4 | 4 |
We have 4 external dependencies:
itextpdf-5.5.6: PDF Rendering (pre downloaded inlibfolder)xmlworker-5.5.6: PDF Generating (pre downloaded inlibfolder)Javafx-11.0.2: The GUI framework (follow this link to download, then unzip)Controlfx-11.0.3: An extension toJavafx(pre downloaded inlibfolder)
Notice that you need
Java 11or later!
First locate the lib folder, then open Project Structure in Intellij IDEA, in the Project tab choose Java 11 or later as Project SDK.
Then click on Libraries tab, then click the + on the top-left comer of the interface, then choose Java from the drop down, then select the lib folder, then OK.
Now click on the + again, then select the openjfx-xxx/lib folder you downloaded previously (add the openjfx-xxx/lib folder not the openjfx-xxx folder).
Then we need to modify the run configuration before we can properly run the program. In Intellij, the easiest way is to first run the program once, notice this run WILL output error messages, but you can ignore it, the purpose of this is to let Intellij to auto configure some things for us.
Go to src/controller/session/ConferenceSystem.java on line 12, you can see the main method and a green run button on the left, click on it then select Run 'ConferenceSystem.main()' (or you can right click on anywhere in the ConferenceSystem.java then select the option from the drop down). Now the console may output a bunch of errors THIS IS OK!
Now on the top bar you should see something like this:
Click on the drop down, then select Edit Configuration then in VM Options copy and paste the following lines:
--module-path
>>>>>>>>>>>>Replace this with Javafx sdk lib folder path on your computer<<<<<<<<<<<<
--add-modules
javafx.controls,javafx.fxml
--add-exports
javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED
--add-exports
javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED
--add-exports
javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED
--add-exports
javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED
--add-modules
javafx.swing,javafx.graphics,javafx.fxml,javafx.media,javafx.web
--add-reads
javafx.graphics=ALL-UNNAMED
--add-opens
javafx.controls/com.sun.javafx.charts=ALL-UNNAMED
--add-opens
javafx.graphics/com.sun.javafx.iio=ALL-UNNAMED
--add-opens
javafx.graphics/com.sun.javafx.iio.common=ALL-UNNAMED
--add-opens
javafx.graphics/com.sun.javafx.css=ALL-UNNAMED
--add-opens
javafx.base/com.sun.javafx.runtime=ALL-UNNAMED
Notice you need to replace the second line with the openjfx-xxx/lib path on your computer!
Now try to run the project again, you should be greeted with the login screen!
-
EventTalk,NonSpeakerEvent,MultiSpeakerEventThese are different kinds of event that happens at the conference. Where
Eventis the parent class of the other three. AnEventcan only be added toScheduleof the conference. -
TaskAppointment,SpeakerDutyThese are different kinds of tasks. Where
Taskis the parent class of the other two. ATaskcan only be added toScheduleof a person. A task is essentially an wrapper for anEvent, meaning every task correspond to one event (but an event could have many tasks), they share the samelocation,startTime,endTime. The reason why we haveTaskis to adapt theEventso that they can be added to the schedule of a person.An example use: every time an organizer assigns a speaker to some event, an
SpeakerDutyis added to the speaker’sSchedule. This way theScheduleof that speaker can ensure the speaker is available at the desired location and time, and no furtherTaskof other events can be added to that occupied location and time, i.e. no double booking of speaker. -
PersonOrganizer,Speaker,Attendee,VIPAttendeeThese are different kinds of
personorpeopleof the conference. WhereOrganizercan organize, andSpeakercan speak, andAttendeecan attend. TheVIPAttendeeis a special kind of attendee, where they have a more than certain amount ofpoints. You can earnpointsbysignupto some events. -
IEventThis is the parent class of
TaskandEvent. AnSchedule<E extends IEvents>object stores a list ofIEvents, here we utilize generic in java to avoid casting. -
OccupancyLevelThis is an
enum, represents how much does anIEventoccupies the location and time it specifies on anSchedule.-
OCCUPANCY_NOThe
IEventwith this type of occupancy does not occupy the time and location it defines. Meaning otherIEventcan still be added to this time and location. For example, anAppointmentshaves no occupancy. -
OCCUPANCY_SPECIFICThe
IEventwith this type of occupancy only occupy the time and location it defines. Meaning otherIEventcan’t occupy this time period at this location specifically, but they can still occupy other time period at this location or other location at this time period. For example,Talk,NonSpeakerEvent,MultiSpeakerEventhas specific occupancy, because there can be otherIEventadded, but needs to be on another location or time. -
OCCUPANCY_ABSOLUTEThe
IEventwith this type of occupancy occupies all location at this time period simultaneously. Meaning no otherIEventcan occupy any location at this time period. For example anSpeakerDutyhas absolute occupancy, because it needs to ensure the speaker is available at the time and location of the event, so does not allow them to have other things at the same time period.
-
-
RelationshipA relationship is basically a mutable integer, it contains a non-negative integer
layerrepresenting how “deep” this relation is, iflayer == 0represents no relation, iflayer >= 1represents has relation. -
MessageStringMessageA Message represents a communication from someone. It contains it’s
content, and asender, andtime. This object is immutable, thus it’s safe to reference from multiple sources. All messages are contained in anChatRecord.
Allows the Organizer to schedule different types of events without worrying about double-booking a location, or double-booking a speaker.
Our program uses an Schedule<E extends IEvent>, which ensures no conflicting IEvent can be added to a Schedule, based on it’s time, location and the OccupancyLevel.
Here IEvent is a parent class of all different events, and all tasks
There are two usage of Schedule, each enforces a feature.
- An
Schedule<Event>for the conference where only containsEventobjects. This is used to ensure no double booking of location and time. - An
Schedule<Task>for each person. This is used to ensure no double booking of speaker.
Allows different types of user to login, and interact with the respective menu interface.
Allow Attendees to sign up to events, and see the schedule of all events.
Allows various types of messaging:
- from Speaker/Organizer to all signed up attendees
- from Organizers to all Speakers/all Attendees
- from Anyone to Anyone else as long as they have some relation (being friends or one is “working” with another)
The program automatically saves all information to a .ser file, this feature utilizes the Serializable interface builtin to java.
In phase 2, the Text UI is replaced by a GUI implemented using Javafx.
Now we have Talk (from phase 1), and the newly introduced NonSpeakerEvent, MultiSpeakerEvent. In addition, they can be an Vip events if they have some requirements to enrol.
There are also some new parameters to an Event, here is the complete parameter list:
| Parameter | Meaning |
|---|---|
title |
The title of the event, two event with the same title is considered recurring events. |
speaker |
The speaker of the event, this field could be different depending on the type of event you create. Talk has exactly one speaker, NoSpeakerEvent has no speaker, and MutiSpeakerEvent has multiple speakers. |
organizer |
The organizer who created this event. |
capacity |
(NEW) This is an number that defines the upper bound of how many people can enrols in this event. This is used to enforce mandatory extension 5. |
location |
Where this event happens. |
startTime |
When this event starts. |
endTime |
When this event ends. |
reward |
(NEW) The reward of this event, people who signed up for this event can earn points defined by this amount. After the attendee has reached a certain amount, they are promoted to an VIPAttendee. If the attendee cancelled the appointment, they lose this amount, and also might demote them to an regular Attendee. |
requirement |
(NEW) The required amount of points an person has to meet in order to attend this event. If this number is greater than 0, then this event is considered as VIP event. |
Now event can be cancelled by the organizer who created it, but only before the events has started.
Now every person has a points, where they can earn by attending events. If their points accumulates high enough, they will be promoted to an VIPAttendee. If their points ever drops below the threshold (by cancelling the appointments to some events) they will be demoted to a regular attendee.
Previously, organizer can create speaker accounts. Now organizer can create Speaker, Organizer, Attendee accounts! Notice that they can’t create an VIPAttendee.
Now everyone has an option to save the schedule of all events as PDF. On the Event tab located on the GUI, you can also have options of searching a specific keywords and selecting which they want to search, here is a screenshot:
On the left drop down, you can select a numbers of options, and the keyword you entered on the right text field would be specific to that search property only.
- All: search everything, any event that satisfied one of the following would be presented.
- Type: search for a type, i.e. “Talk”, “NonSpeakerEvent”, “MultiSpeakerEvent”.
- Title: search for a title.
- Speaker: search for a Speaker’s name.
- Organizer: search for an Organizer’s name.
- Location: search for a location.
- Time: search for a time range, for example: “12:00~13:00” which match all events between 12:00 to 13:00. This feature is implemented using regex.
Scoring system is a supplementary system for providing useful statistic for an Organizer.
Scoring System: when an event has finished (when the end time has passed), all attendees would have an option to give a rating for that event. The rating is from 0 to 5.
After we received some ratings, we can calculate the event’s overall rating as the average rating given by the attendees of that event.
The Speaker’s Rating is given as the average rating of all event’s rating that he is a speaker of.
The statistic we present to the organizers is the top 5 performing speakers, that is the 5 speakers with the highest score.
This info is useful to the organizers, it tells the organizers which speaker is popular, and may helps out the organizers to decide which speaker to assign to the event.
This info is displayed by a bar chat on the Dashboard of all Organizers.
The GUI Framework we choose is JavaFx, using the MVC Structure.
The Views are written in FXML files, and each linked to a specific Controller written in plain java. Here is the relationship of between the stages:
The recommending system uses Collaborative Filtering algorithms to predict the user's preference based on other users with similar preferences. Then recommend the recurring events of the events that the user is predicted to like. Such similarity between users is captured by calculating the Centered Cosine Similarity on their preference vectors. The user’s preferences is the user's rating of the events and is collected by the Scoring System.
There are two main component of the Recommending system:
-
Recommend friends to Attendees.
We recommend a list of people that has a similar preference with the attendee who is logged in.
-
Recommend events to Attendees.
Suppose we are recommending events to an attendee “A”. We first make predictions using collaborative filtering on the preference of “A” to all Events that “A” doesn't have a chance to attend. We recommend the recurring events of the events that “A” is predicted to like.
Both of these recommendations are presented on the Attendee’s Dashboard.
Visitor provides the ability extend a feature without modifying the original class. It also avoids the usages of instanceof and casting.
-
entity.comm.MessageVisitor-
usecase.commu.chat.manager.facade.MessageValidatorCheck if a
Messageis valid. -
usecase.commu.chat.manager.facade.ChatRecordConvertConvert
Messageto Message Data Transfer Object (MessageDTO), to be supplied to the presenter. -
usecase.commu.facade.MessagingConvertConvert
List<ChatManager>to Chat Data Transfer Object (ChatDTO), to be supplied to the presenter.
-
-
entity.event.EventVisitor-
usecase.download.facade.EventDownloadConvert the schedule of events to an HTML formatted string to be outputted as an PDF file (with
gateway.PDFGenerate). -
usecase.event.facade.EventChange.SpeakerChange(private nested class)Apply the change of speaker in an event. The reason for having a visitor is that we have different types of events, some have one speaker, some have no speaker, some have multiple speaker.
-
usecase.event.facade.EventChange.EventUpdater(private nested class)Update the change in event reflected on Speaker’s Task, Speaker’s announcement access, relationship, etc.
-
usecase.event.facade.EventConvertConvert the
Eventto Event Data Transfer Object, to be supplied to the presenter. -
usecase.event.facade.EventCreate.AnnouncementEnroll(private nested class)Update the Announcement Access for the speaker.
-
usecase.event.facade.EventCreate.AttendeeRelationUpdate(private nested class)Update the Attendee’s Relation to speaker and organizer when removing.
-
usecase.event.facade.EventCreate.EventBuilderFactory(private nested class)Construct an event builder based on the event.
-
usecase.event.facade.EventCreate.SpeakerTaskUpdate(private nested class)Update the speaker’s task when creating.
-
usecase.event.facade.EventExtract.ExtractSpeaker(private nested class)Extract the speaker of some event, as a list.
-
usecase.event.facade.EventSignup.SpeakerWorkRelationUpdate(private nested class)Update the work relation of the speaker.
-
usecase.event.facade.EventTypeDistributor.EventTypeExecutor(private nested class)Execute the
EventTypeVisitorwhich is a visitor wrapper for the event visitor. -
usecase.event.facade.EventView.SpeakerMatch(private nested class)Match the speaker of the event by a predicate.
-
usecase.event.facade.EventView.TypeMatch(private nested class)Match the type of the event.
-
usecase.recommand.facade.EventRecommendConvertConvert the
Eventand it’s prediction toEventRecommandDTO, to be supplied to the presenter. -
usecase.score.facade.SpeakerScoreCalculateCalculate the speaker’s score of that event.
-
-
entity.people.PersonVisitor-
usecase.people.facade.PeopleConvertConvert the
Personto Person Data Transfer Object, to be supplied to the presenter. -
usecase.people.facade.PeopleCreateCreate a person, and setup them based on their type.
-
usecase.recommand.facade.PeopleRecommendConvertConvert
Personand it’s similarity toPersonRecommandDTO, to be supplied to the presenter.
-
-
entity.task.TaskVisitor-
usecase.task.facade.TaskConvertConvert
Taskto Task Data Transfer Object (TaskDTO), to be supplied to the presenter.
-
-
usecase.event.EventTypeVisitorThis is basically a wrapper for
EventVisitor. Since the controller shouldn’t access the entity directly, if they want to do operation specific to a type of event, also want to avoidinstanceofas much as possible.-
controller.dialogs.eventEdit.EventInitVisitor(private nested class)Load the edit interface based on the type of the event selected.
-
Facade are used inside the use cases, where one manager does too many things (i.e. has more than one factor to change), thus we use Facade design pattern. Where each sub component is only responsible for a single task.
-
Facade :
usecase.commu.MessagingManage-
usecase.commu.GroupMessagingSending message to multiple people at once.
-
usecase.commu.MessagingConvertConvert
MessagetoMessageDTO. -
usecase.commu.MessagingCreateHandle creating
ChatManager. -
usecase.commu.MessagingViewUpdate the view of a list of
ChatManager.
-
-
Facade :
usecase.commu.chat.manager.ChatManager-
usecase.commu.chat.manager.facade.ChatRecordConvertConvert
ChatRecordtoList<MessageDTO>. -
usecase.commu.chat.manager.facade.MessageValidatorCheck the validity of the message.
-
-
Facade :
usecase.download.DownloadManage-
usecase.download.facade.EventDownloadConvert list of
Eventto HTML formatted style to output.
-
-
Facade :
usecase.event.EventManage-
usecase.event.facade.EventChangeHandle changes made to Event.
-
usecase.event.facade.EventConvertConvert
EventtoEventDTO. -
usecase.event.facade.EventCreateHandle create / remove events.
-
usecase.event.facade.EventExtractExtract some info of an event.
-
usecase.event.facade.EventSignupHandle sign up / cancel sign up to an event.
-
usecase.event.facade.EventTypeDistributorDistribute the
EventTypeVisitor. -
usecase.event.facade.EventViewUpdate the view of a list of events, include applying the
EventSearchPropertyandkeywordas a filter. -
usecase.event.facade.RecurringEventCheckGet the recurring event of a given event.
-
-
Facade :
usecase.event.PeopleManage-
usecase.people.facade.PeopleConvertConvert
PersontoPersonDTO. -
usecase.people.facade.PeopleCreateHandle create person.
-
usecase.people.facade.PeopleFilterHandle filter a list of people by some constrains.
-
usecase.people.facade.PeopleLoginHandle login.
-
usecase.people.facade.PeopleViewUpdate the view of a list of people.
-
usecase.people.facade.VIPPromoteHandle promotion / demotion of person.
-
-
Facade :
usecase.recommand.RecommendManage-
usecase.recommand.facade.CollaborativeFilteringMake the prediction on recommending event.
-
usecase.recommand.facade.EventRecommendConvertConvert to
EventRecommendDTO. -
usecase.recommand.facade.PeopleRecommendConvertConvert to
PeopleRecommendDTO. -
usecase.recommand.facade.SimilarityCalculateCalculate the similarity of two user based on their preference.
-
-
Facade :
usecase.score.ScoreManage-
usecase.score.facade.SpeakerScoreCalculateCalculate the speaker’s score.
-
-
Facade :
usecase.statistic.IStatistic-
usecase.statistic.facade.SpeakerScoreConvertConvert to
SpeakerScoreDTO.
-
-
Facade :
usecase.task-
usecase.task.facade.TaskConvertConvert
TasktoTaskDTO. -
usecase.task.facade.TaskCreateHandle create tasks.
-
usecase.task.facade.TaskViewUpdate the view of a list of task.
-
Factory are used to hide the creation process of a complicated object. Here factory are used to create multiple entities.
-
entity.comm.factory.MessageFactoryCreate a
Messagegiven anObject, and set the current time astime. -
entity.person.factory.PersonFactoryCreate a
Persongiven the name. Provide a method to transform aVIPAttendeetoAttendeeandAttendeetoVIPAttendee, this two method are used when promoting or demoting a person. -
entity.task.factory.TaskFactoryCreate a
Taskgiven anEvent, it set the necessary information from anEventto newly createdTask.
Builder are used to create a complex objects, in step by step fashion.
-
usecase.dto.builder.EventBuilderTalkBuilder,MultiSpeakerEventBuilder,NonSpeakerEventBuilderBecause
Eventis an object that has a lot of parameters, we use a builder to handle its creation process.Here
EventBuilderis an abstract class, contains anbuild()method and contains the common parts.
Observer are used to listen changes from an Observable, to maintain consistency.
-
usecase.friends.manager.RelationshipObservableFriendsManageimplements this interface, it gives the options to add to observe friendship change and add to observe work relation change.-
usecase.friends.manager.RelationshipObserverusecase.commu.chat.manager.DirectChatis anRelationshipObserver, it receives changes to relations, and update the access accordingly.
-
Strategy are used to hide the implementation detail of a feature. That are we want the class to be independent of a particular implementation.
-
usecase.commu.stragergy.AnnouncementNameStrategy,usecase.commu.stragergy.DirectChatNameStrategyHere the algorithm that generates the name of an
AnnouncementorDirectChatis hidden, this way if we want to change the chat name generation algorithm, we can easily swap out the strategy.
| Name | UTROid | Git Name(s) |
|---|---|---|
| Hongcheng Wei | ******** | Hongcheng_Wei, homelet |
| YuHao Yang | ******** | martinyang0416 |
| yi chen liu | ******** | KKKK123454321 |
| Yue Lan | ******** | Yue, kat |
| Yu Sun | ******** | Sunny |
| Zhexuan Li | ******** | royli142857 |
| Qiyue Zhang | ******** | Qiyue Zhang, ma521yyy |
| Peiwen Luo | ******** | flora-luo |
Huge thanks to the TAs and Instructors of CSC207 Fall 2020!
Thanks for reading. Best Appreciate from all team members in Group_0238.


