Skip to content

Commit

Permalink
Merge pull request #226 from AY1920S1-CS2103T-T11-2/yida-5-MoreDocs
Browse files Browse the repository at this point in the history
Housekeeping of UG and DG
  • Loading branch information
kohyida1997 authored Nov 10, 2019
2 parents a67a88e + ed0075c commit dc624c7
Show file tree
Hide file tree
Showing 15 changed files with 220 additions and 111 deletions.
45 changes: 22 additions & 23 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ As commands are stateful, it would be easy to overlook the edge cases when so ma
// tag::settings[]
=== [underline]#Settings Feature#
==== Implementation
`AppSettings` was a class that was created to be integrated into the `Model` of the app. It currently contains these functionalities:
`AppSettings` is a class that was created to be integrated into the `Model` of the app. It currently contains these functionalities:

* `difficulty [EASY/MEDIUM/HARD]` to change the difficulty of the game.
* `hints [ON/OFF]` to turn hints on or off.
Expand Down Expand Up @@ -505,23 +505,21 @@ image::TimerDGScreenshot.png[]

==== Implementation Overview - Timer

The `Timer` component utilizes the `java.util.Timer` API to simulate a stopwatch that runs for each `Card` in a `Game`. It also relies on
using _Functional Interfaces_ as _callbacks_ to periodically notify other components in the system. Using _callbacks_
allows the `Timer` to enact changes in other components of the system without directly holding a reference to those
The `Timer` component utilizes the `java.util.Timer` API to simulate a stopwatch that runs for each `Card` in a `Game`. It relies on
using _Functional Interfaces_ as _callbacks_ for the TImer to periodically notify other components in the system without directly holding a reference to those
components.

Internally, the `Timer`
works by using the method `java.util.Timer.schedule()` that will schedule `java.util.TimerTasks` at a fixed rate (_every 50ms_).
works by using the method `java.util.Timer.schedule()` that schedules `java.util.TimerTasks` at a fixed rate (_every 50ms_).

An _Observer Pattern_ is loosly followed between the `Timer` and the other components. As opposed to defining an
_Observable_ interface, the `AppManager` simply passes in _method pointers_ into the `Timer` to _callback_ when an
event is triggered. The `AppManager` thus works closely with the `Timer` as the main hub to enact changes based on
signals given by the `Timer`.
event is triggered by the `Timer`.

[NOTE]
To avoid
synchronization issues with the `UI` component, all
`TimerTasks` (such as requesting to refresh a component of the `UI`) are forced to run on the *JavaFX Application Thread* using
synchronization issues, all
_callbacks_ to change `UI` components are forced to run on the *JavaFX Application Thread* using
`Platform.runLater()`.

.Class diagram reflecting how the callback-functions are organized in the Timer component.
Expand All @@ -547,9 +545,10 @@ In order to display the `Hints` component to the user in a _Hangman-esque_ style
* Each `Card` contains a `FormattedHintSupplier` that supplies `FormattedHints` ready to be shown to the user.
* Each `FormattedHintSupplier` contains a `FormattedHint` that is periodically updated.
* Each `FormattedHintSupplier` contains a `java.util.List` of `Hint` to update the `FormattedHint` with.
* Each `FormattedHint` maintains a `char[]` array that it's `toString()` method uses to format the output `Hint` string with.
* Each `Hint` encapsulates a `Character` and an `Index` which the `Character` is to be shown in the `FormattedHint`.

The `Timer` component *triggers a request* to the `AppManager`, who then updates and retrieves the `FormattedHint` from
The `Timer` component *triggers a request to update `Hints`* to the `AppManager`, who then updates and retrieves the updated `FormattedHint` from
the current `Game` via the `Logic` component.

==== Flow of Events - `Hints` Disabled
Expand All @@ -563,6 +562,10 @@ image::TimerSequenceDiagram1.png[]
`GameTimer` interface uses a factory method to create `GameTimerManager` instances. This behavior
is omitted in the above diagram for simplicity.

A new `GameTimer` instance is created by the `AppManager` for every `Card` of a `Game`.
The `AppManager` provides information regarding the duration in which the `GameTimer` should run for, and whether
`Hints` are enabled.

. `UI` component first registers _callbacks_ with the `AppManager`.
. When a _Game_ is started, `AppManager` initializes a `GameTimer` instance for the first _Card_.
. `AppManager` registers _callbacks_ with the `GameTimer` component.
Expand All @@ -574,11 +577,6 @@ is omitted in the above diagram for simplicity.

Using this approach of _callbacks_ provides *better abstraction* between the `UI` and `Timer`.

[NOTE]
A new `GameTimer` instance is created by the `AppManager` for every `Card` of a `Game`.
The `AppManager` provides information regarding the duration in which the `GameTimer` should run for, and whether
`Hints` are enabled.

==== Flow of Events - `Hints` Enabled

.Screenshot of the automatic `Hints` feature in action.
Expand All @@ -587,18 +585,19 @@ image::HintDGScreenshot.png[width=790]
.Activity diagram of the `run()` method of an instance of `GameTimerManager` when `Hints` are enabled.
image::TimerActivityDiagramWithHints.png[]

The behavior of `Timer` when `Hints` are enabled is *largely still the same.* +
+
When `Hints` are enabled,
`AppManager` initializes a `HintTimingQueue` in the `GameTimer` for each _Card_. `HintTimingQueue` is a class that
contains a `java.util.Queue` of _timestamps_ (in milliseconds). `GameTimer` polls from the `HintTimingQueue` and checks against
these polled _timestamps_ to update the `Hints` provided periodically. +
+
The described activity is visualized via the activity diagram as *shown above*. The internal `Timer` is started when
* In the diagram as *shown above*, the internal `Timer` is started when
`GameTimerManager` calls the `.schedule()` method of its internal `java.util.Timer`, which schedules `TimerTasks` immediately,
every 50 milliseconds until the `java.util.Timer` is cancelled. The field `timeLeft` is initialized
to be the amount of time allowed per _Card_ (in milliseconds), and is updated every 50ms.

* The behavior of `Timer` when `Hints` are enabled is *largely still the same.*

* When `Hints` are enabled,
`AppManager` initializes a `HintTimingQueue` in the `GameTimer` for each _Card_. `HintTimingQueue` is a class that
contains a `java.util.Queue` of _timestamps_ (in milliseconds). `GameTimer` polls from the `HintTimingQueue` and checks against
these polled _timestamps_ to update the `Hints` provided periodically.


==== Design Considerations

There were a few considerations for designing the `Timer` this way.
Expand Down
78 changes: 41 additions & 37 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -420,23 +420,15 @@ The relevant command(s) are:
Format: `start [EASY/MEDIUM/HARD]`

- Starts a game session with the currently selected _WordBank_ and specified _Difficulty_.
(_WorkBank_ selection is done in _Home_ mode.)

- If no _Difficuty_ is specfied, the default _Difficulty_ in _Settings_
(_WorkBank_ selection is done in _Home_ mode.) If no _Difficuty_ is specified, the default _Difficulty_ in _Settings_
will be used.




==== Game Mode - [underline]#Playing# image:game_mode_icon.png[width="30"]

.UI regions that show feedback during a Game session.
image::UserGuideGameSessionDiagram2.png[width="790"][height="850"]


.Timer and feedback for each Guess during a Game session. (Timer changes color based on time left).
image::UserGuideGameSessionDiagram2.png[width="790"]

During a _Game_, the _Timer_ will change colour according to the time left (region in green box). Feedback for each _Guess_ is shown via the _ResultDisplay_ (region in the red box). +
+
The relevant command(s) are:

1. *Making a _Guess_ for a _Word_*: +
Expand All @@ -458,19 +450,16 @@ Format: `skip`
image::GameFinishedGameStoppedComparison.png[width="1000"]

A _Game_ finishes when *all _Cards_ have been attempted*. _Statistics_ are
*automatically shown* upon completion of a _Game_ (see Fig. 6 above). +
+
The user can choose to `stop` a _Game_ before it has finished. This will result in all current _Game_ progress being lost, and
no _Statistics_ being collected or generated (see Fig. 7 above). +
*automatically shown* upon completion of a _Game_ (see Fig. 6 above). The user can choose to `stop` a _Game_ before it has finished- *all current _Game_ progress is lost*, and
*no _Statistics_ are collected* (see Fig. 7 above). +
+
The relevant command(s) are:

1. *Stopping a _Game_ (before it has finished)*: +
+
Format: `stop`

- Forcibly terminates the current active _Game_ session (*all progress will be lost, and no _Statistics_ will
be reported.*)
- Forcibly terminates the current active _Game_ session.

// end::yida-game[]

Expand Down Expand Up @@ -576,41 +565,42 @@ image::avatar151.png[]
// tag::chenhui-commandusage2[]

=== Misc. Commands
(Help is available in Home mode) +
(Exit is available in any mode except Game mode)
[NOTE]
`help` is available in _Home_ mode +
`exit` is available in any mode *except* _Game_ mode)

==== Ask for help: `help`
Dukemon sends help.
Show the link to the User Guide (appears as a pop-up).

Format: `help`

==== Take a break: `exit`
Dukemon says bye!
Exit and close _Dukemon_.

Format: `exit`

// end::chenhui-commandusage2[]

// tag::statsjason[]
== Statistics image:statistics-icon.png[width="32"]
This section covers the statistics shown to the user.
This section covers the _Statistics_ shown to the user.

=== Game Result
The game result is shown to the user every time they finish a game. It contains information of the finished game and
some information of the _WordBank_.
The game result is shown to the user every time a Game finishes. It contains information regarding the finished _Game_ session and
_Statistics_ for the selected _WordBank_.

We use a simple formula to calculate the score: _floor of_ _(Number of correct answers) / (Total questions) * 100_.

.Game Result UI.
image::annotated_game_results_ui.png[]

=== WordBank Statistics
The _WordBank_ statistics is shown on open mode and contains all information of the _WordBank_.
The _WordBank_ statistics is shown in the _Open_ mode and contains all information regarding the selected _WordBank_.

.Wordbank Statistics UI.
image::annotated_wb_statistics_ui.png[]

NOTE: The high score and fastest clear of a word bank will not be reset on adding/deleting cards.
NOTE: The high score and fastest clear timing of a _WordBank_ will not be reset upon adding/deleting cards.

=== Global Statistics
The global statistics is shown on the main title page and contains all information regarding the user's overall usage
Expand Down Expand Up @@ -649,7 +639,7 @@ image:DragAndDrop3.png[width="130", align="left"]
//image:DragAndDrop3.png[130, 130]

From `HOME` mode, you can view your _WordBanks_. +
Simply drag and drop a _WordBank_ json file from your computer into Dukemon. +
Simply drag and drop a _WordBank_ .json file from your computer into the _Dukemon_ GUI. +

image:DragAndDropOut1.png[width="130", align="left"]
{nbsp} {nbsp} -> {nbsp} {nbsp}
Expand All @@ -662,7 +652,8 @@ your desktop, or chat applications. +

Try it!

NOTE: Dukemon only reads json files.
NOTE: _Dukemon_ only accepts .json files when importing _WordBanks_. Attempting to
import or export other types files will not be successful.

// end::chenhui-userDragAndDrop[]

Expand Down Expand Up @@ -809,15 +800,28 @@ Create your own difficulties with customized time durations.

== FAQ

*Q*: How do I pronounce your app name? +
*A*: Think Pokemon.
*Q*: _Dukemon_ is not starting up/crashes upon load-up, how can I rectify this? +
*A*: Move _Dukemon_ to a new, *empty* file directory. Ensure that all data and configuration files in the same directory are
deleted (_some files may be corrupted_). _Dukemon_ will perform clean start from the new directory.

*Q*: The _Game_ failed to start, what can I do? +
*A*: Ensure that your selected _WordBank_ has at least three _Cards_ to be able to start. Also note that
you will be *brought to the _Game_ mode* regardless, and will need to switch out of it.

*Q*: Switching modes is not working, what can I do? +
*A*: Ensure that *you have selected a _WordBank_* before attempting to switch modes. Check that you have *stopped the _Game_ session*
if you want to switch to certain modes.

*Q*: How do I pronounce the app name? +
*A*: Think _Pokemon_.

*Q*: How do I transfer my _WordBank_ to my friend? +
*A*: Export your _WordBank_ to your computer, then transfer him the file. He can then import the file into his Dukemon.
*Q*: The GUI (Graphical User Interface) seems to be lagging, is this an issue? +
*A*: _Dukemon_ aims to run at around 60fps, but performance varies across machines.

*Q*: How can I transfer/share _WordBanks_ across machines? +
*A*: Use the `export` and `import` functionalities to move data to specific file directories. From there you can
share your files manually.

*Q*: Do I have to save data? +
*A*: Dukemon data are saved in the hard disk automatically after any command that changes the data.
These commands are generally Card/_WordBank_ commands.
There is no need to save manually.
Statistics are also stored automatically.
*Q*: How can I save my data? +
*A*: _Dukemon's_ data is saved to the hard disk automatically (eg. adding cards/words, statistics etc)
There is no need to manually save data or Game `Statistics`.
13 changes: 10 additions & 3 deletions docs/diagrams/HintsClassDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ skinparam arrowThickness 1.2
skinparam arrowColor #0E4100
skinparam classBackgroundColor #654321

package Timer <<Rectangle>> {
Class GameTimer

}

package AppManager <<Rectangle>> {

Class AppManager #00008b {
Expand Down Expand Up @@ -89,10 +94,12 @@ Class FormattedHint #8403fc {
AppManager -right-> Logic
Logic -right-> Model
Model -down-> Game : gets FormattedHints from >
AppManager *-down-> GameTimer : triggers Hint requests <

Game -down-->"0..*" Card : getCurrCardFormattedHint() >
Card *-down-> FormattedHintSupplier : getFormattedHint() >
Card *-right-> Word
Game -down->"0..*" Card : getCurrCardFormattedHint() >
Card *-right-> FormattedHintSupplier : getFormattedHint() >
Card *-left-> Meaning
Card *-down-> Word

FormattedHintSupplier *-down-> FormattedHint
@enduml
6 changes: 3 additions & 3 deletions docs/diagrams/TimerClassDiagramCallbacks.puml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ Class UpdateTimerCallBack <<Interface>> {

}

GameTimer *--down- UpdateHintCallBack
GameTimer *--down- SkipOverCallBack
GameTimer *--down- UpdateTimerCallBack
GameTimer *-down- UpdateHintCallBack
GameTimer *-down- SkipOverCallBack
GameTimer *-down- UpdateTimerCallBack
GameTimerManager -down-|> GameTimer
GameTimer ..left..> AppManager : executes callbacks of >
AppManager --right--> GameTimer : registers callbacks with >
Expand Down
Binary file modified docs/diagrams/powerpoint/Dev Guide Diagrams - Yida.pptx
Binary file not shown.
Binary file modified docs/diagrams/powerpoint/User Guide Diagrams.pptx
Binary file not shown.
Binary file modified docs/images/HintDGScreenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/HintsClassDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/TimerClassDiagramCallbacks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/TimerDGScreenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/UserGuideGameSessionDiagram1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/UserGuideGameSessionDiagram2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit dc624c7

Please sign in to comment.