# Architecture And Module Design Part 1 # Design Document ## For The G-ScalE Mini-Game Battery Project Version 0.1.25 Prepared by Team Ludus [Alice Ip](@ipa1) - 400078727 [Jack Buckley](@bucklj4) - 400144747 [Meijing Li](@lim147) - 400110713 [Shuo He](@hes11) - 400023520 [Yunfei Yang](@yangy113) - 400049426 Instructor: [Dr. Jacques Carette](@carette) Course: [COMPSCI 4ZP6: Capstone Project](https://www.cas.mcmaster.ca/~carette/CS4ZP6/2020_21/index.html) Date: 2020-11-09 Table of Contents ================= [[_TOC_]] # Table of Contents * Revised History * 1 [Likely Changes] (done) * 2 [Unlikely Changes] (done) * 3 [Concepts] (done) * 4 [Module Secrets] (~ 20 pages) * MIS Diagram * Module Lists <!-- the module description --> * Ability Module * Squares (Jack) * Measurement Module * Visuospatial Sketchpad (Jack) * System Module(done) * Helper Module * SquareCanvas (I wrote it, not sure if it's correct. Jack can you double check) * Controller Module (done) * Backend Database (done) * Data transformation (?) <!-- From C# to Elastic search --> * Visualization (done) <!-- Elasticsearch --> * Controller (done) <!-- Unity Action --> <!-- --> * 5 [Module Interface] (~ 20 pages) (Jack) * 5.1 Game Interface ADTs * Image Hit (done) * Catch the Thief (done) * Ball (Shuo) * Circles (done) * Squares (Jack) * 5.2 Abiliy Measurement ADTs (each person does the ability(s) that his/her game measures) * Object Recognition (done) * Inhibition (donw) * Selective Visual (done) * Time to contact(done) * Visuospatial Sketchpad (Jack) * Flicking (done) * 5.3 Overall System Management: * BatterySessionManagement Module done * Player ADT (done) * MiniGame Interface Module (done) * Ability ADT (done) * 5.4 Helper modules / Backend glue (Jack) * Timer (done) * Counter (done) * Position2D (done) * Image (done) * Target (done) * Point (done) * RamGenerator(done) * Cell(done) * SquareCanvas (done) * 5.5 Controller Module (done) * 6 [SRS Changes] (done) * 7 [Dependency Diagram] (?) * 8 [Significant Design] (done) * 9 [Traceability Table] (~ 2 pages) (?) * 10 [Milestone] ## Revision History | Name | Date | Reason For Changes | Version | | ---- | ------- | ------------------- | --------- | | ALL | Nov 13 | First Script | 1.0 | | ALL | Nov 15 | Revised Script | 1.1 | | ALL | Nov 16 | <ul><li>Complete Module Secretes and ADTs</li> | 1.2 | ## 1. Likely Changes <!-- These are the things that might change in the future, either during your implementation, or in some potential future life for your project. Common items here are a) data representation, b) behaviour, c) hardware specifics, d) configuration, e) security requirements. There are, of course, many more categories, the above are just for illustration. The rationale should trace back to the SRS (hopefully with explicit links). --> The following is a list of software aspects for which our product anticipates possible change in the future: * Mini-game compatibility with alternative hardware interface devices - One of the requirements of our product is to have the option to take in game input using various external devices, as necessary for the measurement of target cognitive abilities. [Team Ludus was assigned the task of designing mini-games with the input of just the keyboard and mouse](TODO: Link to AVL-3 in SRS and update AVL-3 (and other mentions of just using the keyboard) to keyboard and mouse). However, as can be seen by [the list of identified [cognitive](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/Software-Requirements-Specification#1211-list-of-lower-order-cognitive-abilities-for-player-model) and [motor abilities](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/Software-Requirements-Specification#1212-fine-motor-actions-divided-by-body-parts), there still remain a large number of identified key motor abilities that require other interface devices to gather data. For example, the shaking motor ability requires the user to move or sway the input hardware using the wrist. For obvious reasons, the keyboard is unable to detect such a movement and, as a result, cannot be used to measure this motor ability. Instead, a hand-held game controller such as a Wii remote that has movement detection hardware/software that is capable of detecting wrist-shaking movements should be used for this specific motor ability measurement. As well, test results for two different hardware interface devices for the same motor ability measurement can be analyzed for differences in performance that may be related to the interface device itself. Other examples of hardware interface devices include Android and other smartphone devices, general game controllers, and VR headsets. * User interface - Possible changes include visual/interface elements and instructional elements that are related to user experience of the product. Such elements include Unity assets, bitmaps, and typography. Requirements such as those pertaining to [ease of use](TODO: link to EU-1), [learning](TODO: link to LR-1), and [usability](TODO: link to UP-2) are verified through formal usability testing and beta testing with external users. As a result, feedback related to necessary user interface changes will not known until a later time and so these elements may undergo significant changes during project implementation. Examples of changes include aspects such as the format, breadth, and quantity of instructions or guidance that the subject requires in order to understand and navigate through each mini game. * Cognitive/motor ability analysis functions - The field of cognitive psychology is a popular and intricate subject of research. As use of technology is further integrated within our society, human-computer interaction in relation to cognitive psychology may reveal new measurement methods and relations between cognitive abilities that can be applied to the analysis of cognitive/motor abilities in our product. It is necessary to update our product in order to ensure that the product provides relevant and accurate information. Changes to the application resulting from novel measurement techniques or advancements in the domain of cognitive psychology allow us to comply with our reliability requirement which mandates that [we measure cognitive and motor abilities in an objective manner that conforms with existing and accepted best practices for measurement](TODO: Link to REL-1). - As we are implementing the software, we will begin to understand technicalities of cognitive ability measurment and interfacing on a more deeper level, and can fine-tune our software to ensure that mini-game parameters such as time spent on a mini-game event is feasible and reasonable for the purposes of measuring the cognitive ability. For example if a majority of players receive a low score, the mini-game may need to be adjusted to be "easier", by modifying parameters so that small changes in ability level can be detected, evaluated, and compared. * Data measurement methods - Currently, our data collection and measurement methods are closely related to the input given by the subject using the hardware interface device. For example, the amount of time between the appearance of the stimulus and the user key press/click may be a factor of the player's aptitude in a particular cognitive ability. However, currently accessible hardware interface devices are incapable of capturing other movement specific details. For example, for the selective visual cognitive ability, and related mini-games, the addition of an eye movement tracking software could provide a very large amount of information about visual processing, by a key press or even the movement of the mouse. For the purposes of [Sasha's research and analysis of cognitive abilities related to video games](TODO: link to the part where we talk about her research), such extensive user data that is only possible with software can be used in fields such as human computer interaction, video game/software development, and cognitive psychology. * Addition of new mini-games - For the scope of our project, [we have decided to focus on a small subset of the total identified cognitive and motor abilities](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/Software-Requirements-Specification#final-product-constraints). However, in the future, Sasha may desire to analyze and measure the aptitude of users in the other abilities. Due to the modular design of our software, it will be possible to design, develop, and add new mini-games to measure and analyze the remaining cognitive and motor abilities, as necessary. ## 2. Unlikely Changes <!-- in this section, please state the changes that are unlikely to happen. These are some thing that will last in our project and we can rely on although it might change. We should provide with explanations about why it will not likely to change, and should linked to the SRS document --> The following is a list of software aspects for which our product will be unlikely to change in the future: * Development environment - [The interface of our project will be developed on Unity. All the code for each mini-game will be written in C#](TODO: <link to the Mandated Constraints>). The design and implementation of the functionality in the mini-games will be achieved using the current Unity libraries. There might be some new technologies that could be used to develop games. However, as our project supervisor, Sasha, imposed [the constraint of using Unity from our very first meeting](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/meetings_with_supervisor/2_october#detailed-notes), we believe it to be unlikely that these core technologies will change in the further design and implementation process. * The selected cognitive and motor ability subset - Currently we have six selected cognitive and motor abilities: [object recognition, inhibition, selective/focused visual attention, time to contact, flicking, and visuospatial sketchpad](TODO: link to 1.5 and update abilities in SRS). The focus of the measurement and analysis will be on these six abilities in this project. The design and implementation of the mini-game will also aim to measure these abilities. Although it is only a subset of the [46 identified cognitive and motor abilities](TODO: Link to Appendix 12.1), and there will be more abilities that need to be measured while we are testing the above abilities, the main focus of our project will not likely to expand broader and [we have long established that our work will only deal with a subset of the abilities](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/meetings_with_supervisor/2_october#meeting-summary). * Measurement interface - The interface or the application of our measurement will be conducted as a series of mini-games. The abilities of subjects will be tested and measured during the time that they are playing the mini-games. The challenges in the mini-games will be used to record the behaviour of players. The game data from the players will be sent to the back-end. Such data will be analyzed to generate a score that should reflect the ability level for the tested ability. Of course the way to measure these abilities may vary in the future, however, in the further development of the project, we will be using mini-games as a tool of measurement.(TODO: Need a link for this sectio) * [Constraints](https://gitlab.cas.mcmaster.ca/bucklj4/capstone-mini-game-battery-project/-/wikis/Software-Requirements-Specification#13-mandated-constraints) (TODO: Link to 1.3) - We have an additional number of contraints that we have previously enumerated in our SRS. These contraints are also long standing and unlikely to change. ## 3. Concepts <!-- in this section, please describe the main idea of the project. There should be several sub-topics such as introduction, background(not sure if necessary), description of the project, some key features, These concepts should be supported with sufficient reason. --> ### Introduction (SRS 1.1a) Our capstone group is developing the G-ScalE Mini-Game Battery Project, a project composed of five single-player mini games designed in Unity, to measure six out of 46 identified human cognitive and psychomotor skills. Each game will take players approximately 30 - 50 seconds to play, and will be used to establish player competencies in a specific cognitive or psychomotor group. The games will be accessible by the players through a web application that runs on a web server, and collects input through the keyboard and mouse. ### Background (SRS 1.1a) The G-ScalE Mini-Game Battery Project is a capstone project for COMPSCI 4ZP6 at McMaster University. This project is developed by Team Ludus, a team that consists of five fourth-year Computer Science students from McMaster University under the supervision of Sasha Soraine. Completion of this capstone project is a mandatory requirement for graduation and also a process for students to apply their knowledge in a year long project. This project is part of the McMaster Gaming Scalability Environment (G-ScalE) research lab, specifically correlates to the research that Sasha Soraine has been conducting. The results of the project will contribute to the work of testing that Sasha has been doing in her PhD research to develop her hypotheses regarding the outcome of mechanical experiences given identified atomic challenges. ### Measurement Mechanism Description The G-ScalE Mini-Game Battery Project is made up of six different short games, and each game can measure one to three different motor and cognitive abilities. The keyboard and mouse are needed for players to complete all ability tests and accurately reflect their actual competency in the tested abilities. In order to successfully measure the abilities, the player will be asked to fill out a questionnaire before the games begin to specify if they have a keyboard and a mouse. The players can still play most of the games if they do not have access to the mouse, and the results will still be generated for the covered abilities, leaving the result of uncovered abilities empty. However, the players cannot play all the games if they do not have access to the keyboard, as the majority of the abilities will be measured through the keyboard input. The G-ScalE Mini-Game Battery Project, during the questionnaire, will record the answers and during the gameplay, will measure the results based on variables like time, accuracy, and distance (including the physical distance between two key strokes and virtual distance between two in-game objects. Multiple types of variables are calculated through the games. When the user completes a game, the program sends a series of previously calculated variables to create numeric data. Once the game set is completed, measurement algorithms will calculate the user's results. These results are captured in an automated and detailed report, compiling the user’s cognitive strengths and weaknesses. ### Characteristics Of Project * The games are designed for users of all ages, however a minimum age of 7 is required so that [the players are able to read and understand the game instructions and correctly interact with the games](TODO: link to EU-2). * The games are free resources and could be accessible online, whereas [the collected data and measurement results will belong to each participate and will be stored in secure fashion](TODO: link to SEC-4). * Testing results will be influenced by players' physical, mental, or sociocultural conditions. Therefore the results only reveal ability levels among a [general population(generic able-bodied neurotypical persons)](TODO: link to 2.4), not in a specific condition group. ### Key Features Of Implementation * The game interfaces will be designed using Unity. * The scripts will be developed using C#. * The backend framework will be driven by Elasticsearch for data storage, analysis and visualization. - The data will be stored in a JSON-like fashion. - Advanced queries over relational databases are supported in processing the database. - Build-in libraries are available for analysis and visualization. - A simple and secured API for C# will be used to transform the gameplay data between game interface and backend in real time. * The game set will be exported as a web application in the WebGL format, available on a public website hosted by a free web server 000Webhost. ### Ability Battery The G-ScalE Mini-Game Battery Project by our team measures the six abilities: Cognitive Ability: - Object recognition - Inhibition - Selective/Focused visual - Time to contact - Visuospatial Sketchpad Fine Motor Ability: - Flicking The following is table to match each ability with the device required: | Ability | Device | |--------------|-----------| | Object recognition | Keyboard | | Inhibition | Keyboard | | Selective/Focused visual | Keyboard | | Time to contact | Keyboard | | Visuospatial Sketchpad | Mouse/Keyboard (Use the mouse by default. If the player does not have a mouse, could still use the keyboard. ) | | Flicking | Mouse | ### Game-Ability Weighting Table: (SRS ) Each mini-game focuses on different cognitive/motor abilities, and may have related abilities that are also tested. As such, the weightage of the data may be different depending on the degree that the ability is tested. The following is a table to match each game to the tested abilitiesand their weightage (where 1 represents high correlation and 5 represents low correlation): | Game Name | Evaluated ability |Weightage | |--------------|---------------|----------| | Image Hit | Object Recognition |1 | | | Inhibition |2 | | Catch The Thief | Selective/Focused Visual |1 | | | Inhibition |2 | | Ball | Time To Contact |1| | Circles | Flicking |1 | | Selective visual |3 | Squares | Visuospatial Sketchpad |1 ### Design/Run Time Concepts: Design time: a concept that appears in your design but not in your code. Run time: a concept that is clearly present in your code. <!-- For example, most things to do with usability will have concepts that only appear at design time, as "the human" tends not to be reified in code (unless you're doing some funky actor-oriented architecture). Efficiency also tends to have artifacts that only appears outside the code itself. --> #### Design Time Concepts: - **User Characteristics** (SRS 2.4): this section defines the characteristics of the user group. The concepts only appears in design as the characteristics of human won't be changed by the code. - **Ease of Use requirements**(SRS 3.1.1): this section defines how easy the application should be when the users navigate it. This concept only appears in design as the ease is pretty objective and couldn’t be addressed by the code. - **Learning Requirements**(SRS 3.1.1): this section defines how quickly the users would be able to learn how to play the games. This concept only appears in design as the learning process varies in individuals and could not appear in the code. - **Understandability and Politeness Requirements, UP-2**(SRS 3.1.1): this table defines the words, symbol and icons used in the UI should be easy to understand. This concept only appears in design as the concept is objective and couldn’t be addressed in the code. - **Hardware Interface** (SRS 3.1.2): this section defines the running environment of the application. It depends on each user’s hardware and OS edition and is not associated with the code. - **Performance** (SRS 3.3.1): the section defines how fast the application will run. It’s related with the efficiency of the programs and it’s outside the code itself. - **Security** (SRS 3.3.2): the section defines how secure the system is. It’s related to the external platform we use and should be outside the code. - **Reliability** (SRS 3.3.3): this section defines how reliable our games are in the measurement of targeted abilities. This concept will be verified through learning and research on cognitive psychology and is outside the scope of the code. - **Compliance**(SRS 3.4): this section defines the rules and compliance we should follow in the software development. It should be outside the code. - **Portability**(3.5.4): this section defines the platform and interface where the application would be able to run. It’s outside the code. - **Cost**(3.5.6): this section defines the cost in the software development. It’s outside the code. - **Interface Verification**(SRS 4): this section defines how the users like our application interface. It could be done through a after-game questionnaire, and is outside the code. - **Cultural Requirements**( SRS 5): this section defines the ethnic rules the games must follow in the presentation of game contents. It’s outside the code. - **Legal Requirements** (SRS 6): this section defines the legal standards we should follow in software development. It’s outside the code. - **Environmental Requirements** (SRS 7): this section defines how our application follows the laws relating to environment protection. It’s outside the code. #### Run Time Concepts: - **PUC Table**(SRS 1.5 Product Scope): this section defines functionalities that our software should have. This concept should clearly appear in the code as each functionality is implemented by a specific method(s) in our game modules(DD 4) and helper modules(DD 4). - **States Table**(SRS 1.5 Product Scope): this section defines the states of games. This concept clearly appears in the code as each state is implemented by a `state invariant` variable in our game modules(DD ) and helper modules(DD ). - **Functional Requirements**(SRS 3.2): this section defines functional requirements that our software should be able to follow. This concept should clearly appear in the code as code is written to fulfill these requirements. Each requirement table will be matched to a specific methods in our module: - `General function requirements` will be matched to `Overall System Management Module` - `Functional requirements for specific games driven from selected abilities` will be matched to `Game Module` and `Ability Module`. - **Implementation** (3.5) - **Maintainability**(3.5.3): the sections define how easy we could maintain the code as well as the system. This concept appears in code as we have the concept in mind to write clean code including give meaningful names to the functions, add comments for clarifications, avoid big chunks of code in one function and use helper functions instead, In this way, the code is easy for later reading, reviewing and updating. - **Reusability**(3.5.4): the section defines how our software could be reused outside this project. This concept appears in code, as we keep this concept in mind to write code in a modular way that contains abstraction layers which would potentially be more powerful than just solving the problems in our project. For example, we have an abstract module `Controller` which will match input events to the trigger variables built in Unity. So far our games only uses keyboard and mouse, but we also leave the freedom to include new input types(e.g. Touchpad, joy-cons) to the games using the `Controller` module. - **Function Verification**(SRS 4): this section defines how we would verify the functional requirements in software development. This concept appears in code, as we would write testing code for the verification. ### Module Interface Specification Notation The notation used in describing the modules' functionality is quite similar to that used in the course COMPSCI 2ME3. We have made some modifications where we saw fit to best describe the syntax and semantics of the interfaces underlying the modules. We describe the notation now: #### Types - $`\mathbb{N}`$: the set of natural numbers - $`\{0, 1, 2, ... \}`$ - $`\mathbb{N}^+`$: the set of *positive* natural numbers - $`\{1, 2, ... \}`$ - $`\mathbb{R}`$: the set of real numbers - $`\mathbb{R}^+`$: the set of *positive* real numbers - $`\{x \in \mathbb{R} | x > 0 \}`$ - $`\mathbb{B}`$: the set of booleans - $`\{\mathtt{True}, \mathtt{False}\}`$ - `[T]`: A sequence of type `T` - i.e. all elements of type `T`, order matters, duplicate elements allowed #### Methods <!-- Most of the ADT follows this syntax:--> - methodName: A method named `methodName` which appears inside the current module - ModuleName.methodName: A method named `methodName` defined in `ModuleName` module and is called outside the `ModuleName` module <!-- - `ModuleName_methodName` : A method named `methodName` which appears in the module `ModuleName` --> #### Definition - `:=`: the assignment operator - `x := y` means `x` is assigned the value of `y` - $x := \begin{cases} E_0 &\text{if $B$ } \\ E_1 &\text{otherwise} \end{cases}$: Expression definition by cases - $`x := E_0`$ if the boolean expression $`B`$ is true; $`x := E_1`$ if the boolean expression $`B`$ is false. - $`E_0`$ and $`E_1`$ are of the same type. - Imperative definition: TODO ## 4. Module Secrets ### MIS Diagram: [To Do] ### List Of Modules: > ##### Module Name > - **Reason for module existence**: > - DESCRIBE THE Purpose of the MODULE AND WHY ITS NEEDED HERE > - **Module Secret**: > - DESCRIBE IMPLEMENTATION SECRETS #### Modules for Abilities ##### SelectiveVisualMeasure - *Reason for module existence*: - The module is for measuring the Selective/Focused Visual cognitive ability. It contains the methods that evaluate the score(s) in game(s) where the users focus attention intentionally on a visual stimuli. - *Module Accessibility*: - The whole module should be hidden from the clients as the clients do not need any information of the module to play the game. - Methods `getThiefScore` and `getCircleScore` are accessible in the modules `Ability` because the two games `Catch The Thief` and `Circles` measure this ability. Therefore we need to create methods to pass sub-scores of two games to the `Ability` and from there calculate the overall score and level for the ability. - *Module Secrete*: - evaluateThiefScore(): The Catch The Thief game has the data that is match to the measurement of selective visual ability. The number of correct presses as well as the duration of the reaction time will be used to derive the score. - evaluateCirclesScore(): The Circles game has minor elements that indicate selective visual ability levels. Such elements include the amount of time it takes for the subject to react to the appearance of the new circle. The `MoveTime` measurement given by the Circles Module will be used for this. Depending on the average `MoveTime` value, a score will be calculated. ##### InhibitionMeasure - *Reason for module existence*: - This module is for measuing the Inhibition cognitive ability. It contains the methods that evaluate score(s) in game(s) where users successfully tune out stimuli that are irrelevant to the task. - *Module Accessibility*: - The whole module should be hidden from the clients as the clients do not need any information of the module to play the game. - Methods `getThiefScor`, `getCircleScore` and `getImageScore` are accessible in the `Ability` mocule because the three games `Catch The Thief`, `Circles` and `Image Hit` measure this ability. Therefore we need to create methods to pass sub-scores of three games to the `Ability` and from there calculate the overall score and level for the ability. - *Module Secrete*: - evaluateThiefScore(): The Catch The Thief game has the data that is match to the measurement of inhibition ability. The number of times that the player correcly avoids the wrong stimulus will be used to derive the score. - evaluateCirclesScore(): The Circles game has minor elements that indicate inhibition ability levels. Such elements include the amount of time it takes for the subject to react to the appearance of the new circle. The `MoveTime` measurement given by the Circles Module will be used for this. Depending on the average `MoveTime` value, a score will be calculated - evaluateImageScore(): It evaluates the Inhibition cognitive ability of the player by deduct scores when he/she misrecognize an image for once in two appearances. It shows the player knows the object, but mispresses the spacebar. This is the presentation of a bad performance on Inhibition ability. ##### FlickingMeasure - *Reason for module existence*: - The module is for measuring the Flicking cognitive ability. It contains the methods that evaluate score(s) in game(s) where users perform the flicking motor ability. - *Module Accessibility*: - The whole module should be hidden from the clients as the clients do not need any information of the module to play the game. - Methods `getCircleScore` is accessible in the `Ability` module because the `Circles` game measures this ability. Therefore we need to create method to pass score of the game to the `Ability` and from there calculate the level for the ability. - *Module Secrete*: - evaluateCirclesScore(): The flicking motor ability module for the Circles game counts the number of successful clicks that the subject completed in relation to the range of the circle, as well as the time of click, using the information given by the Circles module. The number of successful clicks of a range of circle sizes will be counted and the number of successful clicks within a range of times will be used in determining the average time and size that the subject is able to perform the flicking ability. These values will then be quantified into a flicking ability level. If the subject does not click in time, the `MousePositions` list has record of the cursor placement that is also used as an attempt indicator of the flicking ability ##### TimeToContactMeasure - *Reason for module existence*: - This module is for measuing the Time to Contact cognitive ability. It contains the methods that evaluate evaluate score(s) in game(s) where users are able to successfully respond and estimate the moving tagets. - *Module Accessibility*: - The whole module should be hidden from the clients as the clients do not need any information of the module to play the game. - Methods `getContactScore` is accessible in the `Ability` module because the `Ball` game measures this ability. Therefore we need to create method to pass score of the game to the `Ability` and from there calculate the level for the ability. - *Module Secret*: - The Ball require the players to make reaction of a disappear moving target and predict the estimated time that it will arrive a ceartain contact point, this is measuring the coincidence anticipation which is under the time to contact ability. Also, this game is asking players to indicate and compare two approaching target and tell which one is first. This is measuring the ability of relative judgment under time to contact ability. Such mesurement could reflect the time to contact ability of players. ##### Object Recognition Measurement - *Reason for module existence*: - This module is for measuing the Object Recognition cognitive ability. It contains the methods score(s) in game(s) where users are able to identify an object by its physical properties. - *Module Accessibility*: - The whole module should be hidden from the clients as the clients do not need any information of the module to play the game. - Methods `getImageScore` is accessible in the Ability module because the `Image Hit` game measures this ability. Therefore we need to create method to pass score of the game to the Ability and from there calculate the level for the ability. - *Module Secret*: - The method `getGamePlayData` is accessible in the module to get nesessary gameplay data from the game Image Hit. - The function `evaluateScore` is to evaluate the Object Recognition ability of the user. If the user cannot successfully recognize the image for even once, he/she will get deduction of scores in this ability. The player who finishes the correct recognition in a relatively short time-period will get more scores as well. #### Modules for Games ##### ImageHit - *Reason for module existence*: - This module is for setting up the front-end of the `Image Hit` game. It contains the variables and methods that set up the game state and capture raw gameplay data. - *Module Accessibility*: - The display objects(images) are visiable to the clients as they willl need to see the images to interact with the game. Other information shoud be hidden from the clients. - Methods `getGameplayData` is accessible in the `ObjectRecognitionMeasure` and `Inhibition` modules because the players apply Object Recognition and Inhibition abilities in the game, thus the gameplay data contains the raw data used for the ability measurement. We need to create a method to provide such kind of data in this game module. - Module Secret: - In this module, the player will know which types of image they need to recognize at the beginning. Then they should press the spacebar once they find the right type of images during several images consecutively show up. - The method `getGamePlayData` is accessible in the module to get nesessary gameplay data. - The method `ImageHit_init` starts the game, with the initialization of `Generate_type` to specify a category of images which needs to be recognized in this session and `Generate_list` to get the ten images to display. - `Display_type` and `Display_image` show the specified category and all the images respectively. - Once the first ten images are displayed, the images with `ImageMark` of `False` show the misrecognition of the player. Those images should be displayed again, also, three other images should be randomly gotten to display again. This is basically what `Set_additonal_game` does. - `Update_image` ensures the next image is showed once the player press the spacebar or the time passes three seconds. And once the second part of the game ends, `End_game` will make the whole session end. ##### CatchTheThief - *Reason for module existence*: - This module is for setting up the front-end of the `Catch The Thief` game. It contains the variables and methods that set up the game state and capture raw gameplay data. - *Module Accessibility*: - In the module, the screen displaying objects(cells) should be available to the clients as they need to see the objects on the screen to interact with game. All other parts are hidden from the clients because they do not need the information to play the game. - Methods `getGamePlayData` are accessable in the modules`SelectiveVisualMeasure` and `InhibitionMeasure` because the players apply Selective Visual and Inhibition abilities in the game, thus the gameplay data contains the raw data used for the ability measurement. We need to create a method to provide such kind of data in this game module. - *Module Secret*: - In this module, the police and thief image will randomly appear in diffdrent cells on the creen. Whether the images will appear in the current bout and the position of images will be driven by a random generator. - The appearance of iamges, if the player presses the key and the reaction time that the plyer takes for noting the image and press the button would be recoreded for each bout. ##### Circles: - *Reason for module existence*: - This module is for setting up the front-end of the the `Circles` mini-game that captures data for the flicking, object recognition, and selective visual cognitive ability. It contains the variables and methods that set up the game state and capture raw gameplay data - *Module Accessibility*: - In the module, the screen displaying objects(circles) should be available to the clients as they need to see the objects on the screen to interact with game. All other parts are hidden from the clients because they do not need the information to play the game. - Methods `getGamePlayData` are accessable in the modules`SelectiveVisualMeasure`,`InhibitionMeasure`,`FlickingMeasure`, because the players apply selective visual, inhibition, and flicking abilities in the game, thus the gameplay data contains the raw data used for the ability measurement. - *Module Secret*: - The module has a function for calculating the change in the level(`level`), the amount of time between clicks (`levelClickTime`), and levelCircleSize (`levelCircleSize`), which is a main point of interest in testing player ability given changes in click range and time alloted for a click for the flicking ability. The size of the circle and the amount of time to click starts at a standard value. As the player successfully clicks on the circles, the size of the circles decrease and the amount of time allowed decreases as well, to further test the player's abilities. If the player consistently misses the circles at a level, the size and time values stay the same, so that a consistent level can be calculated. The size and time values are recorded for analysis. - The module uses an timer instance to keep track of and store the time when the destination point was generated(`DestinationTime`) and when the player started to move after the destination point appeared (`MoveTime`) using information given by the controller. The module also keeps track of the sequence of clicks done in the game, and positions of the mouse at various points in time including when the round ends, for further flicking measurement, and passes all relevant captured information to the appropriate ability measure module. ##### Ball - *Reason for module existence*: - This module is for setting up the front-end of the `Ball` mini-game. This game is used as the interface to capture the data that could be used to measure and analysis time to contact ability. - *Module Accessibility*: - In the module, the screen displaying moving balls should be available to the clients as they need to see the balls on the screen to interact with game. All other parts are hidden from the clients because they do not need the information to play the game. - Methods `getGamePlayData` are accessable in the `TimeToContactMeasurement` modules because the players apply Time to contact abilities in the game, thus the gameplay data contains the raw data used for the ability measurement. We need to create a method to provide such kind of data in this game module. - *Module Secret*: - The module uses a Target ADT module to represent the moving balls, in this ADT module, the speed and disappear time for each balls are stored as well as the indicator to show which round is the ball in to eliminate duplicattion balls. #### Modules for Overall System: ##### BatterySessionManagement - *Reason for module existence*: - This interface module is for controlling the whole game. It will be able to swith from one mini-game to another and store all the game play data from the mini-game and send them to Elasticsearch for data visulizaion purpose. - *Module Accessibility* - The results of measurement score, level for each ability will be viaible to the clients in the Result Page, as they will be able to see their tesing results. Other information should be hidden from the clients. - *Module Secret*: - The module instance will have a unique ID to identify the user which will be used in the database as primary key. - The play order of the mini-games will be set in advance, such that players will finish game play in a certain flow. - The instruction of each game will be displayed before the game start to help players understand how to control their operation and how to finish the challenges in each mini-game. ##### MiniGame Interface - *Reason for module existence*: - This interface module is a basic interface for all the mini games. - This module controls the instructing displaying, game start and game end. - *Module Accessibility*: - The content of instructions will be visiable to the clients as they need to read instrcuion to understand how to play the game. Other information is hidden fron the clients. - *Module Secret*: - Each game uses this interface to be played by the player. The data gathered of each game will be saved as `Dictionary` type. ##### Player - *Reason for module existence*: - This object module creates an object for each individual player. - *Module Accessibility*: - The player name, age will be visiable to the clients, as this is the information that clients would tell us in the Questionnaire Page. Other information such as userId would be hidden from them. - *Module Secret*: - We will create an Player object for each new pleyer which is to recored the user personal information. ##### Ability - *Reason for module existence*: - This module is for evaluting the overall score and level for each ability. - *Module Accessibility*: - The whole module will be hideen from the clients. - Method `getResult` will be accessed in the `BatterySessionManagement` module to pass the results; method `updateSubScore` will be accessed in the `main` module to insert new seb-score for a ability from a game. - *Module Secret*: - This module stores all sub-scores for abilities from games into a state variable `subScoreSeq`, and then iterates the sequence to caululate the overall score for each ability. The results are saved into another state variable `requltSeq`. - To derive the overall score from the su-scores, the weitage of each game in terms of the cognitive ability is taken into account. #### Helper Modules: ##### Timer - *Reason for module existence*: - This module is for creating timer. - Multiple game modules need to use the timer to click the time between specific actions, that's where the module comes from. - *Module Secrete*: - This module provides methods to do the countdown timer, countup timer as wll as getting current time. - The value of timer is processed in milliseconds in the module, but the displayed timer would be rounded to only show one decimal. ##### Counter - *Reason for module existence*: - This module is for creating counter. - Multiple game modules need to use the counter to count the times that some action happens, that's where the module comes from. - *Module Secrete*: - This module provides methods to initialize a counter, and increament the counter value. ##### Position2D - *Reason for module existence*: - This module is for creating a two-dimentional point which has x-value and y-value. - Multiple game modules need to use the 2D point to speficy the position of game objects, that's where the module comes from. - *Module Secrete*: - This module provides methods to create a `Point` object, set up the x-value and y-value of a point. It also provides methods `getX`, `getY` for getting x-value and y-value from outside. ##### Cell - *Reason for module existence*: - This object module is for cerating a cell object that will be used as a helper module for `CatchTheThef` game module. It contains the position, size, image and status information of each cell. - `Catch The Thief` game requires multiple cells showing on the screen. That's where this object module comes from. - *Module Secrete*: - Each `Cell` has the information of its position on the screen, size, which image appears on it, if it's displaying on the screen. - Ths position and size are fixed as long as a `Cell` project is created; other information could be changed throuh methods `setupImage`, `appearOnScreen` and `disappearFromScreen`. ##### RamGenerator - *Reason for module existence*: - This module is for generating random numbers and boolean values. - Multiple game modules ask for generating random values in setting up the states, that's where the module comes from. - *Module Secrete*: - This module provides two methods for generating numbers. `generateARamNum` will generate a ramdom number between given two range number; `generateARamNumExcludePoint` will generate a random number between given two range number and also the generated random number should be different from the given point. ##### Image - *Reason for module existence*: - This module generates an Image type to store the necessary information for an image in the `Image Hit` game. - *Module Secret*: - Each image has the attributes url, type, and id in our database. - `Image Hit` game needs to record the reaction time before the player presses the spacebar if he/she does so. Thus, `ImageTime` is prepared to satisfy this need. - `Image Hit` game needs to record the whether a player recognizes the current image. Thus, `ImageMark` is prepared to satisfy this need - The methods for creating new `Image` object as well as `Get_type`, `Get_id`, `Get_time`, and `Get_mark` can be accessed in the module `ImageHit` for setting up and get the information of the image. ##### Target - *Reason for module existence*: - This object module is for creating a target object that will be used as a helper module for `Ball` game module. It contains the round, speed and disappear time of each ball target. - *Module Secret*: - `Ball` game require two ball targets in round two to let players judge the order of arrive. That's where this object module comes from. - This objects created by the module are visiable to the users, as the users need to see them on the screen in the gameplay. - The methods for creating new `Cell` object as well as `GetRound`, `GetSpeed`, `GetDisappearTime` can be accessed in the module `Ball` for setting up and get the target information. ##### SquareCanvas - *Reason for module existence*: - This object module is for cerating a list of `Square` object that will be used as a helper function in the `Squares` game. - `Squares` game requires multiple squares showing on the screen in a ramdom postion and a random sebset of them are highlighted one by one. That's where this object module comes from. - *Module Secrete*: - In the object initizalization method, a list of squares in random positions are generated such that there is not overlapping of squares and all square should sit inside the bound. - Method `highlightSquares` will change the color of squares in the specified list to some lighter color for a short period of time and then change its color back one by one. #### Controller Module: ##### Controller - *Reason for module existence*: - This module is for mapping specific input events to the trigger variables `press` and `click`. - In different games, the specified input events could be different. For example, one game requires the players to press the SPACEBAR to interact with the game, whereas another game does not not necessarily require the same button for players to interact. Therefore we need an abstraction layer which we can freely refer different inputs to the same trigger variables in different games. That's where the module comes from. - *Module Srcrete*: - There are two triger variable seutp in the module: `press` and `click`. - The methods in this module for mapping input events to the trigger variables are `pressTrigger`, `clickTrigger` which map events to `press` and `click` respectively. - The methods in the module for changing states of trigger variables are `pressKey`, `releaseKey`, `clickMoseButton`, `releaseMouseButton`. ### Backend Database ##### Storage - **Reason for module existence**: - This module is responsible for permanently storing recorded gameplay data and measurements. It is needed so that this data is retained even after the player has finished playing a gameplay session and closes their browser window. - **Module Secret**: - The implementation secret of this module is to use Elasticsearch as a NoSQL database to store the gameplay data and measurements. The data will be saved to Elasticsearch as a JSON-like object by serializing the in-game C# data objects that we will use to record the measurements. In this way, we can create a 1-1 mapping between the Elasticsearch JSON-like objects and the C# objects and can easily reconstruct the C# object representation using the Elasticsearch representation if need be. ### Data Transformation ### Data Visualization and Storage **[ElasticsearchThe Elk Stack](https://www.elastic.co/what-is/elk-stack)** The visualization and storage of the data collected by our mini-games will be done using ELK stack, otherwise known as Elasticsearch. The ELK stack describes a combination of three popular open-source projects: Elasticsearch, Logstash and Kibana. **[Amazon Elasticsearch Service](https://aws.amazon.com/elasticsearch-service/features/?nc=sn&loc=2)** The Amazon Elasticsearch Service can be used for free with the Amazon Web Services (AWS) Free Tier, to manage setup, deployment, configuration, patching and monitoring of the Elasticsearch clusters. The AWS console allows creation of scalable secure and available Elasticsearch clusters with open source Elasticsearch APIs, Kibana compatability, and integration of Logstash. **[Elasticsearch](https://www.elastic.co/elasticsearch/)** Elasticsearch is a highly scalable and open source search and analytics engine that allows storing, searching, and analyzation of data in a JSON-like fashion. This engine supports advanced queries over relational databases, allowing for greater control over our data analysis. Our data be analyzed to show cognitive ability results using aggregations such as averages, percentiles, and deviations. **Logstash** Logstash is an open source, server-side data processing pipeline used for collecting data from a variety of sources, and loading data into Elasticsearch **[Kibana](https://www.elastic.co/kibana)** Using queries from Elasticsearch, Kibana can be used to visualize data. Kibana offers the ability to represent the data in forms such as histograms, line graphs, pie charts, sunburts, and more, depending on our needs, for each cognitive ability, or for the competency profile as a whole. As of right now, a bar graph will be used to represent the player's competency in the measured cognitive ability. ### Controller **Unity Action** The input trigger in each mini-game will be abstracted as controller layer. For different controller, such layer will be bounded with different concrete method of inputs. The players will not be limited with their hardware device to finish the test. For this abstraction of controller, it could be done with Unity Actions framework which is already been built. The control system of user input detection and game status change will be implemented using `Unity Action` framework as well as the `Controller` Module. ## 5. Module Interface <!-- be careful to not leak the secrets Dr.Smith example: https://gitlab.cas.mcmaster.ca/smiths/se2aa4_cs2me3/-/blob/master/Assignments/A4/A4Soln/Design%20Specification/spec.pdf --> ### 5.1 Game Interface ADTs #### `ImageHit` ADT Module (Yunfei) ---- **Uses** MiniGame Timer RamGenerator Counter Image **Syntax** **Exported Constants**: None **Exported Types**: None **Exported Access Programs**: | **Routine Name** | **In** | **Out** | **Exceptions** | |--------------|----|-----|------------| | ImageHit_init | | | | | getGameplayData | | Seq | | **Semantics** **State Variables** SpecifiedType: `string` <!-- The specified type of images--> ImageList: `Seq` of `Image` <!-- A list of ten images --> SerialNumber: $\mathbb{N}$ <!-- The serial numer of the current image --> AdditionalList: `Seq` of `Image` <!-- A list of images for the second part of the game--> GameplayData: `Seq` **State Invariant** (Image of ImageList & AdditionalList).ImageTime <= 3.00 **Assumptions and Design Decisions** - `SpecifiedType`is the specified category of images. - `ImageList` is list of images displayed on the screen. - `SerialNumber` is the serial numer of the current image. - `AdditionalList` is a list of images for the second part of the game. - `GameplayData` is all the needed gameplay data. **Access Routine Semantics** - ImageHit_init(): - transition: Genarete_type(); Generate_list(); SerialNumber = 0; AdditionalList = [] - output: None - generate_type(): - transition: Use the RamGenerator to select an id from all of the images, and the type of this image is t, SpecifiedType = t - output: None - display_type(): - transition: Display the type of specified images on the top of the screen. - output: None - generate_list(): - transition: Use the RamGenerator to select 3 or 4 ids of images under SpecifiedType, add them in ImageList. Use the Random Generator to select (10 - the amount of images of specifiedType selected before) ids of images under types that are not SpecifiedType, add them in ImageList. $\mathbb{forall}$ i in ImageList, if (i.ImageType = SpecifiedType) => i.ImageMark = `False`; else i.ImageMark =`True`. RandomList(ImageList). - output: None - display_image(Image): - transition: Display the image on the center of the screen. - output: None - set_additonal_game() - transition:If (SerialNumber = 9) ($\mathbb{forall}$ item in ImageList: If (item.ImageMark = `False`) => AdditionalList.Add(item). If (count ($\mathbb{forall}$ item in ImageList: item.ImageMark = `True`) > 3) => (i = 0, while i < 3) $\mathbb{forall}$ item in ImageList: If (item.ImageMark = `True`) => (AdditionalList.Add(item), i+1) ; else => $\mathbb{forall}$ item in ImageList: If (item.ImageMark = `True`) => AdditionalList.Add(item). RandomList(AdditionalList)). ImageList += AdditonalList - output: None - update_image() - transition: If ((The current time of (Trigger.Active("Space") = `True` ) - The current time of the image appears) < 3. | variables | := | | -------------- | ---- | | ImageList[SerialNumber].ImageTime | (The current time of (Trigger.Active("Space") = `True` ) - The current time of the image appears | | ImageList[SerialNumber].ImageMark | bool (1 - ImageList[SerialNumber].ImageMark) | | ImageList[SerialNumber] | += 1 | Display_image(ImageList[SerialNumber]) else | variables | := | | -------------- | ---- | | ImageList[SerialNumber].ImageTime | 3.00 | | ImageList[SerialNumber] | += 1 | Display_image(ImageList[SerialNumber]) - output: None - End_game(): - transition: The game will end once the SerialNumber = the length of ImageList - 1 if SerialNumber > 9. - output: None - getGameplayData(): - transistion: Once the game ends, the necessary data will be gotten. - output: out := GameplayData **Local Functions** RandomList: `Seq` -> `Seq` RandomList(l) == newList that random = new Random(); newList = new `Seq`; $\mathbb{forall}$ (item in l) => newList.Insert(random.Next(newList.Count), item) #### `CatchTheThief` ADT Module (Meijing) ---- **Uses** Controller Cell **Syntax** **Exported Constants**: None **Exported Types**: None **Exported Access Programs**: | **Routine Name** | **In** | **Out** | **Exceptions** | | ----------------- | ------ | -------- | --------------- | | CatchTheThief_init | | | | | getGamePlayData | | Seq | **Semantics** **State Variables** - DeckLength: $`\mathbb{N}^+`$ - Deck: [`Cell`] - BoutId: $`\mathbb{N}`$ - IfThiefAppears: $`\mathbb{B}`$ - IfPoliceAppears: $`\mathbb{B}`$ - ThiefPos: $`\mathbb{N}`$ - PolicePos: $`\mathbb{N}`$ - ImageLatingTime: $`\mathbb{R}`$ - ImageAppearGap: $`\mathbb{R}`$ - IsPressed: $`\mathbb{B}`$ - ReactionTime: $`\mathbb{R}`$ - GamePlayData: `Seq` of ($`\mathbb{N}`$, $`\mathbb{B}`$, $`\mathbb{B}`$, $`\mathbb{N}`$, $`\mathbb{N}`$, $`\mathbb{R}`$ , $`\mathbb{R}`$ , $`\mathbb{B}`$, $`\mathbb{R}`$ ) **State Invariant** - `ThiefPos` $`\not=`$ `PolicePos`: the thief image and police should not appear on the same cell - `PolicePos` $`\in`$ [0, 9) - `ThiefPos` $`\in`$ [0, 9) - 0 $`\leq`$ `BoutId` $`\leq`$ 8: there will be total of 8 bouts in the game **Assumptions and Design Decisions** - `Deck` represents the multiple cells. - `DeckLength` represents the number of cells in a deck. - `BoutId` represents the id of current bout. It start from 1, increased by 1 as a new bout starts. - `IfThiefAppears` represents if the theif image appears in the current bout. - `IfPoliceAppears` represents if the police image appears in the current bout. - `ThiefPos` represents on which cell the thief image appears in the current. - `PolicePos` represents on which cell the police images appears in the current round. - `ImageLatingTime` represents the amount of time that the image remains on the screen - `ImageAppearGap` represents the amount of time between when previous image(s) disappears and when the image(s) in current bout appears on the screen - `IsPressed` represents if the player presses the SPACEBAR in the current bout. - `ReactionTime` represents the time between when image(s) appears and when the user presses the SPACEBAR in the current bout - `GamePlayData` represents all above gameplay data in all bouts - In this game, the players press the SPACEBAR to interact with the game. Thus we need to map SPACEBAR to the trigger variable `press`. **Access Routine Semantics** - CatchTheThief_init(): - transition: - DecLength, Deck , BoutId, GamePlayData:= 9, new Cell[DecLength], 0, [] - Controller.pressTrigger(SPACEBAR) - output: out := self - newBout(): - transition: | variables | := | | -------------- | ---- | | RoundId | RoundId + 1 | | IfThiefAppears | RamGenerator.generateARam<`Bool`>() | | IfPoliceAppears | RamGenerator.generateARam<`Bool`>() | | ThiefPos | if (IfThiefAppears = `True`) $`\Rightarrow`$ RamGenerator.generateARam<`Int`>(1, 9) ; else $`\Rightarrow`$ Null | | PolicePos | if (IfPoliceAppears = `True`) $`\Rightarrow`$ RamGenerator.generateARamExcludePoint<`Int`>(1, 9, ThiefPos); else $`\Rightarrow`$ Null | | ImageLatingTime | RamGenerator.generateARam<`Float`>(3, 5) | | ImageAppearGap | RamGenerator.generateARam<`Float`>(1, 2) | - captureUserReaction(): - transition: | variables | := | | -------------- | ---- | | IsPressed | If (Trigger.Active("Space") = `True`) $`\Rightarrow`$ `True`; else $`\Rightarrow`$ `False` | | ReactionTime | The current time of PRESS - The current time of images appear | - UpdateGamePlayData() - transition: GamePlayData.Insert((`BoutId`, `IfThiefAppears`, `IfPoliceAppears`, `ThiefPos`, `PolicePos`, `ImageLatingTime`, `ImageAppearGap`, `IsPressed`, `ReactionTime`)) - getGamePlayData(): - pre-conditions: BoutId = 8 - output: out := GamePlayData #### Ball Module ---- **Uses** MiniGame Timer Counter Controller **Syntax** **Exported Constants**: None **Exported Types** : None **Exported Access Programs**: | **Routine Name** | **In** | **Out** | **Exceptions** | |--------------|----|-----|------------| | Ball_init | | | | | getGamePlayData | | Seq | | **Semantics** **State Variables**: Round: $\mathbb{N}$ <!-- The round in the Ball game --> Trial: $\mathbb{N}$ <!-- The trial in the Ball game, from round 3 --> Distance: `float` TargetR1: `Target` <!-- The speed of the target in round one --> TargetR2A: `Target` <!-- The speed of the target A in round two --> TargetR2B: `Target` <!-- The speed of the target B in round two --> TargetR3: `Target` <!-- Tbe speed of the trial target in round 3 --> ReferenceTime `float` <!-- The reference time of the complete set of stimult --> RespondTime: `float` <!-- the time when the player respond to the assumed arrival --> PickedTarget: `Target` <!-- the first arrive target that player picked--> ActualTarget: `Target` <!-- the actual target that will arrive first --> TargetEarlier: $\mathbb{B}$ <!-- the decision of the order of the target compared with the reference time --> IsPressed : Sequence of {$\mathbb{B}$, $\mathbb{B}$, $\mathbb{B}$} <!-- Whether the player respond in each round --> GameplayData: Sequence of($\mathbb{N}$, $\mathbb{N}$, `float`, v`Target`, `Target`, `Target`, `Target`, `float`, `float`, `Target`, `Target`, $\mathbb{B}$, Sequence of {$\mathbb{B}$, $\mathbb{B}$, $\mathbb{B}$}) **State Invariant**: `TargetAInRoundTwo.GetSpeed()` $\neq$ `TargetBInRoundTwo.GetSpeed()` : The speed of two targets in round two should be different. **Assumptions and Design Decisions**: - Ball_init() is called before any other methods - `Round`: The round in the Ball game - `Trial`: The trial in the Ball game, range in (1,3) - `Distance`: The distance from the ball to the contact point - `TargetR1`: The speed of the target in round one - `TargetR2A`: The speed of the target A in round two - `TargetR2B`: The speed of the target B in round two - `TargetR3`: Tbe speed of the trial target in round three - `ReferenceTime`: The reference time of the complete set of stimult - `RespondTime`: The time when the player respond to the assumed arrival - `PickedTarget`: The first arrive target that player picked - `ActualTarget`: The actual target that will arrive first - `TargetEarlier`: Whether the target arrive earlier than reference time - `IsPressed` : Whether the player respond in each round.each round - `GameplayData`: The all gameplay data above **Access Routine Semantics**: - Ball_init(): - transition: | Variables | := | | -------------- | ---- | | Round, Trial, ReferenceTime,RespondTime, Distance | 0 | | TargetR1, TargetR2A, TargetR2B, TargetR3| new Target | | PickedTarget, ActualTarget| new Target | | TargetEarlier | False | | IsPressed, GameplayData | [] | - output: self - exception: None - getGamePlayData(): - pre-conditions: Round = 3 - output: out := GamePlayData **Local Function**: - StartGame(): - transition: | Variables | := | | -------------- | ---- | | Round | 1 | | TargetR1| new Target(1,RamGenerator.generateARam<`Float`>,RamGenerator.generateARam<`Float`> | | GameTime | Timer.getTime() | | Distance | RamGenerator.generateARam<`Float`> | - output: None - exception: None - NextRound(): - transition: if round = 1, then | Variables | := | | -------------- | ---- | | Round | 2 | | TargetR2A TargetR2B|new Target(2,RamGenerator.generateARam<`Float`>,RamGenerator.generateARam<`Float`>| if round = 2, then | Variables | := | | -------------- | ---- | | Round | 3 | | TargetR3 |new Target(3,RamGenerator.generateARam<`Float`>,0)| | Trial | 1| |ReferenceTime| RamGenerator.generateARam<`Float`> | - output: None - exception: None - RespondToAssumedTime(): - pre-conditions: Round = 1 - transition: | Variables | := | | -------------- | ---- | | isPressed | If (Trigger.Active("A") = `True`) => isPressed.append(true) | | GameTime | Timer.getTime() - GameTime | | RespondTime | GameTime - TargetR1.GetDisppearTime() | - output: None - exception: None - ChooseTarget(): - pre-conditions: Round = 2 - transition: | Variables | := | | -------------- | ---- | | isPressed | If (Trigger.Active("A") = `True`) or If (Trigger.Active("B") = `True`) => isPressed.append(true) | | PickedTarget | If (Trigger.Active("A") = `True`) => `TargetR2A`; If (Trigger.Active("b") = `True`) => `TargetR2A` | - output: None - exception: None - NextTrial(): - pre-conditions: Round = 3 - transition: | Variables | := | | -------------- | ---- | | Trial | Trial + 1 | | TargetR3 |new Target(3,ramdRamGenerator.generateARam<`Float`>,ramdRamGenerator.generateARam<`Float`>)| |ReferenceTime| ramdomTimeer | - output: None - exception: None - IndicateOrder(): - pre-conditions: Round = 3 - transition: | Variables | := | | -------------- | ---- | | isPressed | If (Trigger.Active("E") = `True`) or If (Trigger.Active("L") = `True`) => isPressed.append(true) | | EarlyOrLater | If (Trigger.Active("E") = `True`) => `True`; If (Trigger.Active("L") = `True`) => `False` | - output: None - exception: None - UpdateGamePlayData() - transition: GamePlayData.Insert((`Round`, `Trial`, `Distance`, `TargetR1`, `TargetR2A`, `TargetR2B`, `TargetR3`, `ReferenceTime`, `RespondTime`, `PickedTarget`,`ActualTarget`,`TargetEarlier`,`IsPressed`)) #### Circles Module (Alice) **Uses** MiniGame Timer Counter Controller Position2D **Syntax** **Exported Constants:** None **Exported Types** : None **Exported Access Programs**: | **Routine Name** | **In** | **Out** | **Exceptions** | |--------------|----|-----|------------| |Circles_init | | | | |getGameplaydata | |Seq | | **Semantics** **State Variables**: Level: $`\mathbb{N}`$ <!-- Difficulty level of the destination point --> LevelClickTime: $`\mathbb{R}^+`$ <!-- Duration that destination point remains on the screen --> LevelCircleSize: $`\mathbb{R}^+`$ <!-- The radius of the destination point --> OriginPoint: `Position2D` <!-- x,y, of mouse position when destination point appear --> DestinationPoint: `Position2D` <!-- x,y of destination circle --> DestinationTime: $`\mathbb{R}^+`$ <!-- Time when destination point appeared --> MoveTime: $`\mathbb{R}^+`$ <!-- Time when player started to move after destination point appeared --> Clicks: Seq of ($`\mathbb{R}^+`$,$`\mathbb{R}^+`$, Seq of ($`\mathbb{R}^+`$,`Position2D`)) <!-- [level, [(time, position)]], Sequence of clicks that the player makes within a level, including the time when the click was done, and the position of the click--> EndPoint: `Position2D` <!-- x,y of mouse at the end of the level --> MousePositions: Seq of (level, Seq of ($`\mathbb{R}^+`$,`Position2D`)) <!-- [level, [(time, position)]], Sequence of mouse positions that the player is in within a level, including the record time, and the position --> GameplayData: Seq of [(`Position2D`, `Position2D`, $`\mathbb{R}^+`$, $`\mathbb{R}^+`$, Seq of (level, Seq of ($`\mathbb{R}^+`$,`Position2D`)), Seq of (level, Seq of ($`\mathbb{R}^+`$,`Position2D`)))] <!-- Seq of [(OriginPoint, DestinationPoint, DestinationTime, MoveTime, Clicks, MousePositions] --> GTimer: `Timer` <!-- Timer for entire minigame --> LTimer: `Timer` <!-- Timer for current level --> ClickTime: $`\mathbb{R}^+`$ HitCount: $`\mathbb{N}`$ <!-- Number of circles clicked within range --> TotalCount: $`\mathbb{N}`$ <!-- total number of circles seen in game --> MaxClickTime: $`\mathbb{R}^+`$ WaitTime: $`\mathbb{R}^+`$ MINX: $`\mathbb{R}^+`$ MAXX: $`\mathbb{R}^+`$ MINY: $`\mathbb{R}^+`$ MAXY: $`\mathbb{R}^+`$ **State Invariant:** - GameTimer $\lt$ 60 - MaxClickTime = 60 - MINX $\leq$ 200 - MAXX $\leq$ 200 - MINY $\leq$ 200 - MAXY $\leq$ 200 **Assumptions and Design Decisions:** - `Level` represents Difficulty level of the destination point. - `LevelClickTime` represents the duration that destination point remains on the screen. - `LevelCircleSize` represents the radius of the destination point - `OriginPoint` represents x,y of mouse position when destination point appear - `DestinationPoint` represents x,y of destination circle - `DestinationTime` represents the time when the destination point appeared - `MoveTime` represents the time when player started to move after destination point appeared - `Clicks` represents the sequence of clicks that the player makes within a level, including the time when the click was done, and the position of the click - `EndPoint` represents the x,y of mouse at the end of the level - `MousePositions` represents the Sequence of mouse positions that the player is in within a level, including the record time, and the position - `GameplayData` - represents all above gameplay data in mini-game - `GTimer` - GameTimer Instance for mini-game - `GTimer` - GameTimer Instance for level - `WaitTime` - Amount of time that game waits before moving to the next level - To ensure there is meaningful and complete data about the flicking motor ability, the locations of the circles are not completely random. First, the player must click the circle in the middle of the screen, then another circle will be generated at a random position. The third circle will be generated in the middle of the screen. - As a result of the previous point, starting from level 0, every even numbered level consists of a circle in the center of the screen. **Access Routine Semantics:** Circle_init(): - transition: | Variables | := | | -------------- | ---- | | Level, DestinationTime, MoveTime | 0 | | LevelClickTime | 5 | | LevelCircleSize | 10 | | Clicks, MousePositions, GameplayData | [] | | OriginPoint, DestinationPoint, EndPoint | new Position2D| | GTimer,LTimer | new Timer| - output: self - exception: None **Local Functions:** StartGame(): - transition: GTimer.Start() - output: execute NextLevel() and displayLevel() - exception: None NextLevel(): - transition: | Variables | := | | -------------- | ---- | | Level | CalculateNextLevel() | | OriginPoint | Controller.getCursorPos() | | DestinationTime| GameTimer.getTime()| | GameTimer| GameTimer.getTime()| - output: displayLevel() - exception: None FirstMove(): - transition: MoveTime=GameTimer.getTime() - output: None - exception: None OnClick(): * transition: Clicks = Clicks.insert(LevelClickTime, levelCircleSize,[GameTimer,getTime(), Controller.getCursorPos()] ) * output: None * exception: None RecordPosition(): * transition: MousePositions = MousePositions.insert(LevelClickTime, levelCircleSize,[GameTimer,getTime(), Controller.getCursorPos()] ) * output: None * exception: None EndLevel(): * transition:GameplayData.insert(OriginPoint, DestinationPoint, DestinationPoint, DestinationTime, MoveTime, Clicks, MousePositions) * output: None * exception: None DisplayCircle(x,y,s): * transition: displays a circle at the x,y position of size s * output: None * exception: None SuccessfulClick(): - transition: - output: For all clicks in the list, if the distince of the click to the center of the point is within the radius, return True - exception: CalculateNextLevel(): - transition: | Condition | Variable Assignment | | -------------- | ---- | | 0 |WaitTime = MaxClickTime | | 1 |LevelClickTime = LevelClickTime - 0.25 first, then WaitTime = LevelClickTime | | 2 |WaitTime = MaxClickTime | | 3 |LevelCircleSize = LevelCircleSize - 1 first, then WaitTime = LevelClickTime | - output: None - exception: None QualifyNextLevel(): - transition: | Condition | Condition 1 |Condition 2 | | -------------- | ---- | --- | | $SuccessfulClick() = True$ |Level = (Level + 1)%3 | | | $SuccessfulClick() = False$ |Level = 1, |Level = Level - 1 then LevelClickTime = LevelClickTime + 0.25 | | $SuccessfulClick() = False$ |Level = 3, |Level = Level - 1 then LevelClickTime = LevelClickTime - 0.25 first, then WaitTime = LevelClickTime | - output: None - exception: None GeneratePosition(): - transition: | Variables | := | | -------------- | ---- | | DestinationPoint.x | generateARam<`Float`>(MINX, MAXX) | | DestinationPoint.y | generateARam<`Float`>(MINY, MAXY) | - output: None - exception: None PlayLevel(): - transition: - output: Use GeneratePosition() to randomize the destination point coordinates then use DisplayCircle(DestinationPoint.x,DestinationPoint.y, LevelCircleSize) to show the Circle on the screen. Then set LTimer to be LevelClickTime. When LTimer reaches 0 or subject clicks on the circle, then execute QualifyNextLevel() then NextLevel() - exception: None #### `Square` ADT Module ----- **Uses** - TODO **Syntax** **Imported Constants** - `SQUARE_CANVAS_WIDTH`: $`\mathbb{R}^+`$ - `SQUARE_CANVAS_HEIGHT`: $`\mathbb{R}^+`$ **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