# Architecture and Module Design Part 2
### 5.2 Ability Measurement ADTs
#### `Se
lectiveVisualMeasure` ADT Module
------
CatchTheThief
Circles
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
None
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| getThiefScore | | $`\mathbb{N}`$ | |
| getCircleScore | | $`\mathbb{N}`$ | |
**Semantics**
**State Variables**
- `cd`: `Seq`
- `circlesd`: `Seq`
- `thiefScore`: $`\mathbb{N}`$
- `imageScore`: $`\mathbb{N}`$
**State Invariant**
None
**Assumptions and Design Decisions**
- $`0 \leq thiefScore \leq 100 \land 0 \leq circleScore \leq 100`$: the score is evaluated over 100
- In the measurement based on Catch The Thief game, a correct press in a short amount of time will result in a higher `score`.
**Access Routine Semantics**
- getGamePlayData()
- Transition: cd, circlesd = CatchTheThief.getGamePlaydata(), Circles.getGamePlayData()
- evaluateThiefScore()
- Transition:
| | **:=** |
|--------------|----|
| thiefScore | <ul>$`\forall cd.BouId: `$<li>$`cd.IfThiefAppears \land \lnot cd.IfPoliceAppears \land IsPressed \Rightarrow score + 5`$</li> <li>$`cd.IfThiefAppears \land IsPressed \land cd.ReactionTime < 2 \Rightarrow score + (2-cd.ReactionTime)*5`$</li> |
- evaluateCirclesScore()
- Transition: Calculate average `MoveTime` value:
averageReactionTime = $`\forall c \ in \ circlesd, (\sum c.MoveTime) \div circlesd.size() `$
| | **:=** |
|--------------|----|
| circleScore | <ul><li>Average Value for `MoveTime` = 5 $`\Rightarrow`$ 60 </li> <li>Average Value for `MoveTime` = 4 $`\Rightarrow`$ 70 </li> <li>Average Value for `MoveTime` = 3 $`\Rightarrow`$ 80 </li><li>Average Value for `MoveTime` = 2 $`\Rightarrow`$ 90 </li> <li>Average Value for `MoveTime` = 1 $`\Rightarrow`$ 100 </li>|
- getThiefScore()
- Output: out := thiefScore
- Exception: None
- getCirlceScore()
- Output: out := circleScore
- Exception: None
#### `InhibitionMeasure` Module
----
**Uses**
CatchTheThief
ImageHit
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
None
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| getThiefScore | | $`\mathbb{N}`$ | |
| getImageScore | | $`\mathbb{N}`$ | |
**Semantics**
**State Variables**
- `od`:`Seq`
- `cd`: `Seq`
- `thiefScore`: $`\mathbb{N}`$
- `imageScore`: $`\mathbb{N}`$
**State Invariant**
None
**Assumptions and Design Decisions**
- $`0 \leq thiefScore \leq 100 \land 0 \leq imageScore \leq 100`$: the score is evaluated over 100
- In the measurement based on Catch The Thief game, a success void of pressing when the Police appears will result in a higher `score`.
- In the Image Hit game, if the player misrecognizes the image for one time, his gameplay data will be reflected in measurement of this ability.
**Access Routine Semantics**
- getGamePlayData()
- Transition:
|Variable | **:=** |
|--------------|----|
| cd |CatchTheThief.getGamePlayData() |
| od | ImageHit.getGameplayData()|
- evaluateThiefScore()
- Transition:
| | **:=** |
|--------------|----|
| thiefScore | <ul>$`\forall cd.BoutId: `$ <li>$`cd.IfThiefAppears \land cd.IfPoliceAppears \land \lnot IsPressed \Rightarrow score + 5`$</li> <li>$`cd.IfThiefAppears \land cd.IfPoliceAppears \land IsPressed \Rightarrow score - 5`$</li> <li>$`\lnot cd.IfThiefAppears \land cd.IfPoliceAppears \land \lnot IsPressed \Rightarrow score + 5`$</li> <li>$`\lnot cd.IfThiefAppears \land cd.IfPoliceAppears \land IsPressed \Rightarrow score - 5`$</li> |
- evaluateImageScore()
- Transition: Set the intial imageScore as 100. For every unique image.ImageId in ImageList, if its corresponding image.ImageMark is `False` for only one time, imageScore - 10.
- evaluateCirclesScore()
- Transition: Calculate average `MoveTime` value:
averageReactionTime = $`\forall c \ in \ circlesd, (\sum c.MoveTime) \div circlesd.size() `$
| | **:=** |
|--------------|----|
| circleScore | <ul><li>Average Value for `MoveTime` = 5 $`\Rightarrow`$ 60 </li> <li>Average Value for `MoveTime` = 4 $`\Rightarrow`$ 70 </li> <li>Average Value for `MoveTime` = 3 $`\Rightarrow`$ 80 </li><li>Average Value for `MoveTime` = 2 $`\Rightarrow`$ 90 </li> <li>Average Value for `MoveTime` = 1 $`\Rightarrow`$ 100 </li>|
- getThiefScore()
- Output: out := thiefScore
- Exception: None
- getImageScore()
- Output: out := imageScore
- Exception: None
#### `ObjectRecognitionMeasure` Module
----
**Uses**
ImageHit
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
None
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| getImageScore | | $\mathbb{N}$ | |
**Semantics**
**State Variables**
- `od`: `Seq`
- `imageScore`: $\mathbb{N}$
**State Invariant**
None
**Assumptions and Design Decisions**
- $` 0 \leq imageScore \leq 100`$ : the score is evaluated over 100
- In the Image Hit game, if the player recognizes the image correctly for one time, his gameplay data will be reflected in measurement of this ability.
**Access Routine Semantics**
- getGamePlayData()
- transition: od = ImageHit.getGameplayData()
- output: None
- evaluateImageScore()
- transition:
- For first ten images in ImageList, if image.ImageMark is `True`, `imageScore` + 8; else, for the images started from the eleventh, if the image.ImageMark with the same image.ImageId turns to `True`, imageScore + 8.
- In this way, the highest score player can get is 80. Players with great performance of average image.ImageTime (only counts when it != 3. and image.ImageMark is `True`) may get different bonus points from the rest 20 points.
- output: none
- getImageScore()
- transition: none
- Output: out := imageScore
#### `TimeToContactMeasurement` Module
**Uses**
Ball
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
None
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| getContactScore | | $`\mathbb{N}`$ | |
**Semantics**
**State Variables**
- `GameData` : `Seq`
- `contactScore`: $`\mathbb{N}`$
**Assumptions and Design Decisions**
- Init is called before any other method
- $`0 \leq contactScore \leq 100`$: the score is evaluated over 100
- In the Ball game round one, the more accurate that estimated time of the target to arrive at contact point would result in higher score.
- In the Ball game round two, the short time for player to pick the correct target will result in higher score.
- In the Ball game round three, the more correct trials will result in higher score.
**Access Routine Semantics**
- Init()
- Transition:
| | **:=** |
|--------------|----|
|GameData |Ball.getGamePlayData()|
|contactScore | 0|
- getContactScore()
- Output: out := contactScore
- Exception: None
- evaluateScore()
- Transition:
| | **:=** |
|--------------|----|
|contactScore | <ul>GameData<li>$`GameData.RespondTime = GameData.DistanceR1 \div GameData.TargetR1.GetSpeed() \Rightarrow score + 5`$</li><li>$`GameData.RespondTime - GameData.DistanceR1 \div GameData.TargetR1.GetSpeed() \in (0,1] \Rightarrow score + 3`$</li><li>$`GameData.RespondTime - GameData.DistanceR1 \div GameData.TargetR1.GetSpeed() \in (1, 2] \Rightarrow score + 1`$</li><li>$`GameData.PickedTarget = GameData.TargetR2A \land GameData.TargetR2B.GetSpeed()\le GameData.TargetR2A.GetSpeed() \Rightarrow score +5`$</li><li>$`GameData.PickedTarget = GameData.TargetR2B \land GameData.TargetR2B.GetSpeed() \ge GameData.TargetR2A.GetSpeed() \Rightarrow score +5`$</li><li>$`GameData.DistanceR3 \div GameData.TargetR3.GetSpeed() > GameData.ReferenceTime \land GameData.TargetEarlier = False \Rightarrow score +5`$</li><li>$`GameData.DistanceR3 \div GameData.TargetR3.GetSpeed() \le GameData.ReferenceTime \land GameData.TargetEarlier = True \Rightarrow score +5`$ |
#### `FlickingMeasure` ADT Module
------
**Uses**
Circles
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| getCircleScore | | $`\mathbb{N}`$ | |
**Semantics**
**State Variables**
- `circlesdata`: `Seq`
- `circleScore`: $`\mathbb{N}`$
**State Invariant**
None
**Assumptions and Design Decisions**
- $`0 \leq ciecleScore \leq 100`$: the score is evaluated over 100
**Access Routine Semantics**
- getGamePlayData()
- Transition: circlesdata := Circles.getGamePlayData()
- calculateCircleScore()
- Transition: tempScore = 100, $\forall$ entries in circlesd, calculate the scores for each, calculate an average, and use the averages to calculate an average circleScore. Values for `LevelClickTime`** and `LevelCircleSize` are rounded down to the nearest value
For successful clicks, values are rounded down:
| **Values for `LevelClickTime`** | **Score** |
|--------------|----|
| 5 | 30 |
| 4 | 40 |
| 3 | 50 |
| 2 | 60 |
| 1 | 70 |
| 0.75 | 80 |
| 0.5 | 90 |
| 0.25 | 100 |
| **Values for `LevelCircleSize`** | **Score** |
|--------------|----|
| 10 | 55 |
| 9 | 60 |
| 8 | 65 |
| 7 | 70 |
| 6 | 75 |
| 5 | 80 |
| 4 | 85 |
| 3 | 90 |
| 2 | 95 |
| 1 | 100 |
If the player did not successfully click, there is still a score calculated with relation to`LevelCircleSize` and `LevelClickTime`. If the player was very close to the circle radius, or on the circle radius, they would get a higher score for their attempt.
- getCircleScore()
- Output: out := circleScore
- Exception: None
### 5.3 Overall System Management:
#### `BatterySessionManagement` Module
----
**Uses**:
Storage
Timer
Ability
**Syntax**
**Exported Constants**: None
**Exported Types** : None
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Init | String, ℕ | | |
**Semantics**
**State Variables**:
usr: string
sessionId: ℕ
games: [MiniGame]
gameData: [GameData]
measureResult: [(AbilityName, ℕ, AbilityLevel)]
batteryStartTime: $`\mathbb{R}`$
batteryEndtime: $`\mathbb{R}`$
**State Invariant**:
**Assumptions and Design Decisions**:
- `usr` is a string that is global unique. It's to identify each player.
**Access Routine Semantics**:
- Init(usr, sessionId):
- transition: batteryStartTime = Timer.getTime(), Storage.store(usr,sessionId)
- output:None
- exception:None
- StoreData(m):
- transition:
- games.append(m)
- m.init()
- m.getInstructions()
- m.play()
- Storage.store(sessionId, (user, sessionId, games, m.getGamePlayData())
- output: None
- exception: None
- Endsession():
- pre-condition: length of gameData = 5 $`\land`$ length of games = 5
- transition:
batteryEndTime = Timer.getTime()
- output:None
- exception:None
- Measure():
- pre-condition: length of gameData = 5 and length of games = 5
- transition:
measureResult = Ability.getResult()
- output:None
- exception:None
- SendData():
- transition: None
- output:measureResult
- exception:None
#### `Player` ADT Module
----
**Uses**:N/A
**Syntax**
**Exported Constants**: None
**Exported Types** : None
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Init |string, ℕ, ℕ | | |
**Semantics**
**State Variables**:
name: string
userId: $`\mathbb{N}`$
age: $`\mathbb{N}`$
**State Invariant**:
**Access Routine Semantics**:
Initialize(s,n):
* transition: name = s, id = n
* output: None
* exception: None
**Local Functions**: None
#### `MiniGame` Interface Module
----
**Uses**:N/A
**Syntax**
**Exported Constants**: None
**Exported Types** : None
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Init | | | |
| Play | | | |
| GetGameplayData | | `Dictionary`<`Object`, `Object`> | |
| DisplayInstructions| | | |
**Semantics**
**State Variables**:
**State Invariant**:
**Assumptions and Design Decisions**:
- Init is called before any other method.
**Access Routine Semantics**:
- Init():
* transition: None
* output: None
* exception: None
- Play():
* transition: The game session is active.
* output: None
* exception: None
- GetGameplayData():
* transition: The game data will be gotten.
* output: The data will be output as the `Dictionary` Type.
* exception: None
**Local Functions**:
- DisplayInstructions():
* transition: Move to instruction scene
* output: Displays instructions for game on screen
* exception: None
#### `Ability` ADT Module
----
**Uses**:
SelectiveVisualMeasure
InhibitionMeasure
ObjectRecognitionMeasure
TimeToContactMeasurement
FlickingMeasure
VisuospatialSketchpadMeasure
**Syntax**
**Exported Constants**: None
**Exported Types** : None
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| UpdateSubScore |AbilityName, GameName, $`\mathbb{N}`$, $`\mathbb{R}`$ | | |
| getResult | | Seq | |
**Semantics**
**State Variables**:
- `subScoreSeq`: [(AbilityName, GameName, $`\mathbb{N}`$, $`\mathbb{R})]`$
- `requltSeq`: [(AbilityName, $`\mathbb{N}`$, AbilityLevel)]
**State Invariant**:
None
**Assumptions and Design Decisions**
- This module imports all measurement modules as it need to call methods from them to get score of the ability in games.
- `subScoreSeq` is a list of tuples, where the tuple has the ability name, the game name, the score of the ability in that game, and the weightage of that game in terms of the cognitive ability, i.e. (AbilityName, GameName, Score, Weight)
- Weightage value should be in the range (0, 1].
- `resultSeq` is a list of tuples, where the tupe has the ability name, the overall score of the ability, and the level of the ability, i.e. (Abilityname, Score, Level)
**Access Routine Semantics**:
- Initialize(s):
* transition: subScoreSeq, resultSeq = [], []
* output: None
* exception: None
- UpdateSubScore(gameName,abilityName, newScore,weightage):
* transition: subScoreSeq = $` subScoreSeq || (abilityName, gameName, newScore, weightage)`$
* output: None
* exception: $` newScore > 100 ∨ newScore < 0 ⇒ invalid\_argument `$
- calculateResult():
* transition: resultSeq = $`\forall x \in AbilityName • resultSeq || (x, s, l)`$ where $`s = calculateOverallScoreForOneAbility(x)`$, $`l = evaluateLevel(s)`$
* output: None
* exception: None
- getResult()
* transition: None
* output: out := resultSeq
**Local Functions**:
- calculateOverallScoreForOneAbility(aName):
* transition: None
* output:
$`∀ s ∈ subScoreSeq \land s.AbilityName = aName • (∑ s.score * s.weightage)/ (∑ s.weightage) `$
* exception: None
<!-- https://math.stackexchange.com/questions/2445193/how-to-calculate-weighted-average-when-the-weights-do-not-equal-100-percent -->
- evaluateLevel(score)
- Output:
| | **:=** |
|--------------|----|
| out | <ul><li>$`90 < score \leq 100 \Rightarrow Excellent`$</li> <li>$`75 < score \leq 90 \Rightarrow Good`$</li> <li>$`50 < score \leq 75 \Rightarrow Okay`$</li> <li>$`25 < score \leq 50 \Rightarrow Poor`$</li><li>$`0 \leq score \leq 25 \Rightarrow Very Poor`$</li>|
**Local Types**
- AbilityName = {Object Recognition, Inhibition, Selective Visual, Time To Contact, Visuospatial Sketchpad, Flicking}
- GameName = {Image Hit, Catch The Thief, Ball, Circles, Squares}
- AbilityLevel = {Excellent, Good, Okay, Poor, Very Poor}
### 5.4 Helper modules / Backend glue
#### `Timer` Module
----
**Uses**:N/A
**Syntax**
**Exported Constants**: None
**Exported Types** : None
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| CountDownStart | | $`\mathbb{R}`$ | |
| CountUpStart | | | |
| GetTime | | $`\mathbb{R}`$ | |
| DisplayTime | | | |
**Semantics**
**State Variables**:
currentTime:float
startingTime: float
timerText: string
**State Invariant**:
currentTime ≥ 0
startingTime ≥ 0
**Access Routine Semantics**:
- countDownStart(i):
* transition:
- startingTime = i
- decrementUpdate()
* output: None
* exception: i < 0 ⇒ IndexOutOfBoundsException
- countUpStart(i):
* transition:
- startingTime = 0
- incrementUpdate()
* output: None
* exception: None
- GetTime():
* transition: none
* output: out := currentTime
* exception: None
DisplayTime():
* transition:
| Conditon 1 | Condition 2 | Output |
|------------------|--------------------|--------------------------------------------------------------------------|
| currentTime > 5 | True | window := displays timerText ^ timerText.colour = black |
| currentTime ≤ 5 | currentTime ≥ 0.1 | window := displays timerText ^ timerText.colour = red |
| | currentTime < 0.1 | window := displays timerText ^ currentTime = 0 ^ timerText.colour = red |
**Local Functions**:
- incrementUpdate():
* transition: currentTime decreases by 0.1 after 0.1 seconds
* output: None
* exception: None
- decrementUpdate():
* transition: currentTime decreases by 0.1 after 0.1 seconds
* output: None
* exception: None
#### `Counter` Type Module
----
**Uses**:N/A
**Syntax**
**Exported Constants**: None
**Exported Types** : None
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Initialize | | | |
| GetCounter | | ℕ | |
| Increment | | | |
**Semantics**
**State Variables**:
value:ℕ
**State Invariant**:
value ≥ 0
**Access Routine Semantics**:
Initialize():
* transition: value = 0
* output: None
* exception: None
GetCounter():
* transition: none
* output: out := value
* exception: None
Increment():
* transition: value += 1
* output: None
* exception: None
**Local Functions**:
Update():
* transition: currentTime decreases by 0.1 after 0.1 seconds
* output: None
* exception: None
#### `Position2D` ADT Module
----
**Uses**
None
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
- `Position2D`
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Position2D_init | ($`\mathbb{R}`$, $`\mathbb{R}`$) | | |
| Position2D_getX | | $`\mathbb{R}`$ | |
| Position2D_getY | | $`\mathbb{R}`$ | |
**Semantics**
**State Variables**
- `x`: $`\mathbb{R}`$
- `y`: $`\mathbb{R}`$
**State Invariant**
None
**Assumptions and Design Decisions**
- The first argument is the `x` position, and the second argument is the `y` position
**Access Routine Semantics**
- `Position2D_init(x', y')`
- Transition: (`x`, `y`) := (`x'`, `y'`)
- Exception: None
- `getX()`
- Output: `x`
- Exception: None
- `getY()`
- Output: `y`
- Exception: None
#### `Image` Module
----
**Uses**
N/A
**Syntax**
**Exported Constants**: None
**Exported Types**:
Image = `Seq` of (Url, ImageType, ImageId, ImageMark, ImageTime)
**Exported Access Programs**:
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Get_type | | string | |
| Get_id | | $\mathbb{N}$ | |
| Get_mark | | $\mathbb{B}$ | |
| Get_time | | float | |
**Semantics**
**State Variables**
Url: `string` <!-- The url of the image-->
ImageType: `string` <!-- The type of the image-->
ImageId: $\mathbb{N}$ <!-- The id of the image-->
ImageMark: $\mathbb{B}$ <!-- The mark that whether an image is recognived correctly by the player-->
ImageTime: `float` <!-- The time that one image remains on the screen-->
**State Invariant**:
**Assumptions and Design Decisions**
- This type is about the information of an image we need for the game Image Hit.
- Assume each image has the attributes url, type, and id in our database.
- `ImageType`is the category of the image.
- `ImageId` is the id of the image.
- `ImageTime` represents the time that one image remains on the screen
- `ImageMark` represents the mark that whether an image is misrecognived by the player.
**Access Routine Semantics**
- Get_type():
- transition: none
- output: out := ImageType
- Get_id():
- transition: none
- output: out := ImageId
- Get_mark():
- transition: none
- output: out := ImageMark
- Get_time():
- transition: none
- output: out := ImageTime
#### `Target` ADT module
----
**Use**
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
- `Target`
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Target_init | (float, float, float) | | Speed >0 |
| Target_GetRound | | float | |
| Target_GetSpeed | | float | |
| Target_GetDisappearTime | | float | |
**Semantics**
**State Variables**
Round: $\mathbb{N}$
Speed: float
DisappearTime: float
**State Invariant**
`Speed` > 0
**Assumptions and Design Decisions**
- The first argument is the `Round` that the target is used
- The second argument is the `Speed` of the moving target
- The third arugument is the `DisappearTime` of the moving target
**Access Routine Semantics**
- `Target_init(Round', Speed', DisppearTime')`
- Transition: (`Round`, `Speed`, `DisppearTime`) := (`Round'`, `Speed'`, `DisppearTime'`)
- Exception: `Speed` > 0
- `GetRound()`
- Output: `Round`
- Exception: None
- `GetSpeed()`
- Output: `Speed`
- Exception: None
- `GetDisappearTime()`
- Output: `DisppearTime`
- Exception: None
#### `Point` ADT Module
----
**Uses**
**Syntax**
**Imported Constants**
**Imported Types**
- `Position2D`
**Exported Constants**
- `SQUARE_WIDTH`: $`\mathbb{R}^+ = TODO`$
- `SQUARE_UNHIGHLIGHTED_COLOUR`: `SquareColour` = `SquareColour.PURPLE`
- `SQUARE_HIGHLIGHTED_COLOUR`: `SquareColour` = `SquareColour.YELLOW`
**Exported Types**
- `Square`
- `SquareColour` = {`PURPLE`, `YELLOW`}
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| Square_init | `Position2D` | | |
| Square_flipHighlight | | | |
| Square_isHighlighted | | $`\mathbb{B}`$ | |
| Square_getPosition | | `Position2D` | |
**Semantics**
**State Variables**
- `currentColour`: `SquareColour`
- `position`: `Position2D`
**State Invariant**
- (`currentColour` = `SQUARE_UNHIGHLIGHTED_COLOUR`) $`\lor`$ (`currentColour` = `SQUARE_HIGHLIGHTED_COLOUR`)
**Assumptions and Design Decisions**
- `Square_init` is called before any other method.
- `position` gives the position of the top left corner of the square.
**Access Routine Semantics**
- `Square_init(p)`
- Transition: (`position`, `currentColour`) := (`p`, `SQUARE_UNHIGHLIGHTED_COLOUR`)
- Exception: None
- `Square_flipHighlight()`
- Transition: $\mathtt{currentColour} := \begin{cases}
\mathtt{SQUARE\_UNHIGHLIGHTED\_COLOUR} &\text{if $\mathtt{currentColour} = \mathtt{SQUARE\_HIGHLIGHTED\_COLOUR} $} \\
\mathtt{SQUARE\_HIGHLIGHTED\_COLOUR} &\text{otherwise}
\end{cases}$
- Exception: None
- `Square_isHighlighted()`
- Output: $`\mathtt{currentColour} = \mathtt{SQUARE\_HIGHLIGHTED\_COLOUR}`$
- Exception: None
- `Square_getPosition()`
- Output: `position`
- Exception: None
#### `RamGenerator` ADT Module
------
**Uses**
None
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
None
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| generateARamBool | | $`\mathbb{B}`$ | |
| generateARamNum | (`T`, `T`) | `T` | |
| generateARamNumExcludePoint | (`T`, `T`, `T`) | `T` | |
**Semantics**
**State Variables**
- `from` : `T`
- `to`: `T`
- `excludedP` : `T`
**State Invariant**
None
**Assumptions and Design Decisions**
- T specifies a numeric data type, including $`\mathbb{N}`$, $`\mathbb{R}`$
- `from` < `to`
**Access Routine Semantics**
- `generateARamBool()`:
- output: out := randomly pick a boolean from {`True`, `False`}
- Exception: None
- `generateARam<T>(from, to)`
- Output: out := randomly pick a value `r` such that: $`r : T | r \in [from, to]`$
- Exception: None
- `generateARamExcludePoint<T>(from, to, excludedP)`
- Output: out := randomly pick a value `r` such that: $`r : T | r \in [from, to] \land r \neq excludedP`$
- Exception: None
#### `Cell` ADT Module
----
**Uses**
Position2D
**Syntax**
**Imported Constants**
None
**Imported Types**
None
**Exported Constants**
None
**Exported Types**
- `Cell`
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| init | (Position2D, $`\mathbb{N}`$, $`\mathbb{N}`$) | | |
| setupImage | `ImagetSet` | | |
| appearOnScreen | | Screen Display Change | |
| disappearFromScreen | | Screen Display Change | |
**Semantics**
**State Variables**
- `p`: Position2D
- `width`: $`\mathbb{N}`$
- `height`: $`\mathbb{N}`$
- `image`: ImageSet
- `status`: StatusSet
**State Invariant**
None
**Assumptions and Design Decisions**
- `width` and `height` should be in appropriate values such that that nine cells could be displayed nicely on the screen.
**Access Routine Semantics**
- `init(point, w, h)`
- Transition: p, width, height, status := point, w, h, Off
- Exception: None
- `setupImage(img)`
- Transition: image := img
- Exception: None
- `appearOnScreen()`
- Transition: status = On
- Output: the cell displays on the screen with the image shown on position `p` with `width` and `height`.
- Exception: None
- `disappearFromScreen()`
- Transition: status = "Off"
- Output: the cell disappears from the screen
- Exception: None
**Local Types**
- ImageSet = {Police, Thief, Empty}
- StatusSet = {On, Off}
#### `SquareCanvas` ADT Module
----
**Uses**
- `Square`
**Syntax**
**Imported Constants**
- `SQUARE_WIDTH`
**Imported Types**
- `SquareColour`
**Exported Constants**
- `SQUARE_CANVAS_WIDTH`: $`\mathbb{R}^+`$ = TODO
- `SQUARE_CANVAS_HEIGHT`: $`\mathbb{R}^+`$ = TODO
- `SQUARE_HIGHLIGHT_INTERVAL`: $`\mathbb{R}^+`$ = TODO
- `SQUARE_HIGHLIGHT_DURATION`: $`\mathbb{R}^+`$ = TODO
**Exported Types**
- `SquareCanvas`
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| SquareCanvas_init | `[Position2D]` | | `X_OUT_OF_BOUNDS`, `Y_OUT_OF_BOUNDS` |
| SquareCanvas_highlightSquares | `[Position2D]` | | `NO_MATCHING_SQUARE` |
| Square_isHighlighted | | $`\mathbb{B}`$ | |
**Semantics**
**State Variables**
- `squares`: `[Square]`
**State Invariant**
- $`\forall s: \mathtt{Square} | s \in \mathtt{squares} \land 0 \le \mathtt{s.getPosition().getX()} \le \mathtt{SQUARE\_CANVAS\_WIDTH} - \mathtt{SQUARE\_WIDTH} \land
0 \le \mathtt{s.getPosition().getY()} \le \mathtt{SQUARE\_CANVAS\_HEIGHT} - \mathtt{SQUARE\_WIDTH}`$
**Assumptions and Design Decisions**
- `SquareCanvas_init` is called before any other method.
**Access Routine Semantics**
- `SquareCanvas_init(ps)`
- Transition: $`\mathtt{squares} := [p: \mathtt{Position2D} | p \in ps : \mathtt{Square\_init}(p)]`$
- Exception:
- $`(\exists p: \mathtt{Position2D} | p \in ps \land 0 \le \mathtt{p.getX()} \le \mathtt{SQUARE\_CANVAS\_WIDTH} - \mathtt{SQUARE\_WIDTH}) \Rightarrow \mathtt{X\_OUT\_OF\_BOUNDS}`$
- $`(\exists p: \mathtt{Position2D} | p \in ps \land 0 \le \mathtt{p.getY()} \le \mathtt{SQUARE\_CANVAS\_HEIGHT} - \mathtt{SQUARE\_WIDTH}) \Rightarrow \mathtt{Y\_OUT\_OF\_BOUNDS}`$
- `Square_highlightSquares(ps)`
- Operation: $`\forall p : \mathtt{Position2D} | p \in ps :
\begin{cases}
\mathtt{getSquare}(p).\mathtt{flipHighlight()} \\
\mathtt{Timer.wait(SQUARE\_HIGHLIGHT\_DURATION)} \\
\mathtt{getSquare}(p).\mathtt{flipHighlight()} \\
\mathtt{Timer.wait(SQUARE\_HIGHLIGHT\_INTERVAL)} \\
\end{cases}
`$
- Exception: Possible `NO_MATCHING_SQUARE` exception propagation from `getSquare`.
**Local functions**
- `getSquare(p)` : $`\mathtt{Position2D} \rightarrow \mathtt{Square}`$
- Output: $`[s : \mathtt{Square} | s \in \mathtt{squares} \land p = s.\mathtt{getPosition()} : s][0]`$
- Exception: $`\lnot (\exists s: \mathtt{Square} | s \in \mathtt{squares} \land p = s.\mathtt{getPosition()}) \Rightarrow \mathtt{NO\_MATCHING\_SQUARE}`$
### 5.5 Controller Module (Meijing)
#### `Controller` ADT Module
**Uses**
None
**Syntax**
**Imported Constants**
None
**Imported Types**
Key
MouseButton
**Exported Constants**
None
**Exported Types**
None
**Exported Access Programs**
| **Routine Name** | **In** | **Out** | **Exceptions** |
|--------------|----|-----|------------|
| pressTrigger | `Key` | | |
| clickTrigger | `MouseButton` | | |
| pressKey | | | |
| releaseKey | | | |
| clickMouseBotton | | | |
| releaseMouseButton | | | |
**Semantics**
**State Variables**
- `press`: Key
- `click`: MouseBotton
- `isPressing`: $`\mathbb{B}`$
- `isClicking`: $`\mathbb{B}`$
**State Invariant**
None
**Assumptions and Design Decisions**
- `press` and `click` are two input triggers that would be applied in the Unity Action Framework.
- `pressTrigger` method must be called before `pressKey` and `releaseKey` called.
- `clickTrigger` method must be called before `clickMouseButton` and `releaseMouseButton` called.
**Access Routine Semantics**
- pressTrigger(key):
- Transition: `press` := key
- Exception: None
- clickTrigger(mouseButtom):
- Transition: `click` = mouseButton
- Exception: None
- pressKey()
- Transition: `isPressing` := `True`
- releaseKey()
- Transition: `isPressing` := `False`
- clickMouseButton()
- Transition: `isClicking` := `True`
- releaseMouseButton()
- Transition: `isClicking` := `False`
**Local Types**
- Key = a set of name of keys on keyboard
- MouseButton = {Right Button, Left Button}
## 6. SRS Changes
<!-- in this part, should list all the changes that we made to the SRS documents. It shoudl be something from the feedback of SRS or anything that we want to change during the design process -->
<!-- SRS changes, clear communication of the SRS changes (10 marks) -->
For all the content mentioned in this section, please refer to our SRS document. The URL is: https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/Software-Requirements-Specification
* 1.2 Stakeholders: The wider McMaster and academic audience for video game research should be added to the subsection **Others**.
* 1.5 Product Scope: Since we decided to change some games, this part needs a significant revision.
* Product Boundary
The cognitive abilities we focus on now are: **Object Recognition**, **Time To Contact**, **Selective/focused Visual**, **Inhibition**, and **Visuospatial Sketchpad**.
The motor ability we focus on is **Flicking**.
* Game 1: The first game now is **Image Hit**. The cognitive abilities about this game now are **Object Recognition** and **Inhibition**. The way we gamify our measurement of those abilities changes accordingly.
Instruction:
Ten different images will be shown on the screen one by one and 3-4 images will belong to the same image type. When the user sees an image from the specified type, they should press the SPACEBAR as quickly as possible. When the user sees an image not from the specified type, they shouldn’t press any key. A set of three random images will be shown a second time. The wrongly identified card will also be shown a second time.
* Game 2: The second game now is **Catch The Thief**. The cognitive abilities about this game now are **Selective/focused visual**, **Inhibition**. The way we gamify our measurement of those abilities changes accordingly.
Instruction:
There are nine squares on the screen in a 3x3 array. Every 2 seconds, on these squares, a thief image or a police image may appear (images should not appear on the same square) for a short period before disappearing again. If the thief image appears on a square, the player must press SPACEBAR as fast as possible, If the police image appears, the player must refrain from pressing SPACEBAR until only the thief image is on the screen.
* Game 3
The third game now is **Ball**. Compared with the former **Ball** game, the motor ability, **Pressing**, is now not under our consideration.
Instruction:
Round 1: moving target disappears from view before it reaches the contact point. The subject is then required to make a response that coincides temporally with the target’s assumed arrival at the contact point (CA task).
Round 2: Subjects indicate which of two approaching targets will arrive first after they disappear (RJ task).
Round 3: Observers indicate on each trial whether a single target would arrive at a contact point earlier or later than the the mean time of arrival for the complete set of stimuli, which served as a form of internalized reference time (RJ task.
* Game 4
The fourth game now is **Circles**. The cognitive abilities about this game now are **Object recognition** and **Selective visual**. The motor abilities about this game now are **Flicking**. The way we gamify our measurement of those abilities changes accordingly.
Instruction:
A 3D screen is shown with a circle on the screen. The player must click on the center of the circle. After each click (regardless of whether it was in the circle), another circle is generated on the screen, and the player must move the mouse to click on the next circle. As the round continues, the game begins to generate smaller and smaller circles.
* Game 5
The fifth game now is **Squares**. The cognitive abilities about this game now is **Visuospatial Sketchpad**. The way we gamify our measurement of this ability changes accordingly.
Instruction:
Squares on the screen are shown in some order.Player then must reproduce the placement of the squares in the same order that it was lit up. There are several rounds, where in the later rounds, the block position and order is shown at a faster speed.
Mouse version: the user taps on the square to indicate which square is selected.
Keyboard version: map each square to a unique key on the keyboard.
* Product Use Case
Use cases should be modified to adapt new games. Cases about previous games should be removed. Cases need to be removed include PUC 8 to 11, 15 to 19, 30 to 34, and potentially more. Necessary cases about new games should be added.
* 1.6 Definitions, Acronyms and Abbreviations: Abilities which not considered in our previous games should be listed in the subsection **Domain-specific terminology**.
* 2.5 Assumptions and Dependencies: More assumptions should be stated.
* 3.2 Functional: Due to significant changes to games, functional requirements need to be rewritten mostly. Functional requirements need to be changed include FCS-1 to 4, FM-1 to 9, FB-1, FHS-1 to 6, FFC-1 to 6, and potentially more. Accordingly, necessary functional requirements on our new games should be added.
## 7. Dependency Diagram
<!-- in this section, please give a workflow of all the modules. In the workflow, the order and structure of the modules in the project should be displayed. Such as, when module A finished, or information from X are received, the next modules will start. It must be a 'depends on' diagram. Usually make a circle diagram is bad idea.
-->

## 8. Significant Design
<!-- state the significant algorithms or maintain non-trivial in-variants in the modules-->
The G-ScalE Mini-Game Battery Project has three major goals that require non-trivial functions:
1. Collect accurate and relevant cognitive/motor ability data.
2. Calculate/Analyze the subject's aptitude in the cognitive/motor abilities.
3. Display the subject's ability level.
To ensure that our product fulfills all requirements as stated by the
[Software Requirements Specification](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/Software-Requirements-Specification#3-requirements), and fit industry software quality standards, our software design focuses on concepts such as maintainability, separation of concerns, modularity for the interaction of the modules.
**1. Collect accurate and relevant cognitive/motor ability data.**
For goal 1, One of the major points of interest is BatterySessionmanagement Module, the main module responsible for invoking the instances of each mini-game. The software undergoes the following general steps after initialization of the BatterySessionManagement module and the player data:
1.The BatterySessionManagement module calls a mini-game module.
2.Mini-game executes and gathers gameplay data.
3.When mini-game gameplay is complete, gameplay data is sent to the related cognitive ability measurement modules.
4. The related cognitive ability measurement modules calculates a score depending on the mini-game, and send the data to the ability module.
5. When whe mini-game module returns, the BatterySessionManagement module calls the next mini-game module.
6. Repeat steps 2-5 until all the mini-games have been executed.
7. BatterySessionManagement module calls the Ability ADT Module to calculate scores and gets the subject's ability scores for the tested cognitive/motor abilities.
The following is a sequence diagram of an example of how one loop of steps 1-5 may look like using actual modules in the software.

**2. Calculate/Analyze the subject's aptitude in the cognitive/motor abilities.**
As seen in the [module secrets](https://hackmd.io/sF-TI-HXT32HiOXFOBedPQ#4-Module-Secrets) section, separate modules are made, one for each mini-game, and one for each cognitive ability. In this way, modules can be catagorized into:
- Game Interface ADTs Modules: Each mini-game has it's own module for collecting cognitive ability data
- Abiliy Measurement ADTs Module: Each module in this category only evaluates one cognitive/motor ability
- Overall System Management Modules: General modules that server as a template for the modules that inherit functions and properties, as well as modules that manage the other modules
- Helper modules: Modules that perform tasks or represents data that can be decoupled from other modules to perform functions as per separation of concerns
**3. Display the subject's ability level.**
As seen in the [Data Visualization](https://hackmd.io/sF-TI-HXT32HiOXFOBedPQ#Data-Visualization-and-Storage), section, visualization and analysis portions of the software are decoupled and modularized. The ELK stack https://hackmd.io/0KLKGH3_S06nlKJxZ1MK_Q?both#mentioned in the mentioned section consists of several portions that will be used in combination with our modules:
- Logstash, the interface and pipeline for transfering cognitive ability data to Elasticsearch
- Elasticsearch, the interface for data query of subject cognitive/motor ability levels, generation of a player profile and analysis/comparison with existing subject data
- Kibana, the interface for displaying the ability level.
### Life Cycle
The below are life cycle disgrams for designing the system as well as running time of the application.
#### Designing System

Note:
- The inner cycles indicates that the parts were sent for client review and refined based on the feedback.
- Touchpoint document is a short document(within 10 pages) that provides high-level key points of design decisions. It is sent to Sasha to gather feedback before expanding on it and making it formal in our official design document. The touchpoint document could be found [here](https://docs.google.com/document/d/1z5ArBJVRzXONMq-AhfL-B4Y7H9EhDYsFcpcD75kgmJI/edit).
#### Running Games

Note:
- The Questionnaire Page requires the users to fill their accessible devices(keyboard, mouse), age, name.
- The duration of reading instruction for each game is no more than 10 seconds; the duration of playing each round of the game is 20 to 40 seconds.
- The duration of generating the results of ability battery in the Result Page is no more than 5 seconds.
## 9.Traceability Table
A table for matching the sections of design doc to SRS. <!-- To make the traceability more specific for marking purpose.-->
## 10. Milestone
| Meeting Agenda | Time |
| ---- | ------- |
| Collaborate with group to go over the first version of scripts | Friday 5:30pm |
| Second meeting with group | Sunday 12:00pm |
| Third meeting with group | Monday morning 8:00am, Lunch(time to be discussed on msger) |
| Send the doc to TA & Prof to review | Next Monday afternoon at 3:00 |