Results Analysis
Data Format
Tests results are stored on the tablet, Gitlab and TabSINT server in JSON and CSV (optional) formats. Each exam session is saved as a separate file. The schema for the JSON result file is below in Results Schema. If an RSA public key is provided in the protocol, the result files are encrypted and stored in a .txt
base64 format on the tablet and on Gitlab (results are not encrypted on the TabSINT server). More details on the data encryption is provided in the Data Encryption section.
JSON Format
Exam results can be downloaded in their native JSON format. JSON can be loaded into most analysis environments, including Python and MATLAB (using the JSONLab toolbox).
JSON-formatted exam results contain all of the information that was uploaded to the server in a highly accessible format. It is the best format for advanced post-processing of results in MATLAB or Python.
CSV Format
The CSV format is easy to load and may be the easiest format to use for simple or ad-hoc post-processing. CSV files can be opened in most spreadsheet programs, including Microsoft Excel. Viewing in Excel is helpful for a "quick-look" at the data.
Only results from a Multiple Input, Multiple Choice, Text Box, Likert, Triple Digit Test, MPANL, the WAHTS Calibration Check or audiometry (specifically Manual Audiometry, Hughson Westlake, BHAFT, Bekesy Like, Bekesy MLD) response area can be exported and displayed in a CSV flattened format. To enable export to CSV, set exportToCSV
: true
. Response areas that have exportToCSV
: true
will be exported to a CSV file in the internal storage directory Documents/tabsint-results
/[name-of-your-protocol]
. If your protocol specifies that the results should be encrypted, the CSV file will be encrypted in the same way as the JSON file.
Only the following fields will be exported to CSV:
- Info/input fields:
- Tablet UUID
- Protocol Name
- Exam Start Date
- TabSINT version
- Firmware Tag
- WAHTS Serial Number
- Calibration Date
- Results fields:
- Ear
- Frequency (Hz) (threshold frequency for chaBHAFT)
- Threshold
- Threshold Units
- Result Type (provide information if threshold could not be calculated)
- Textbox
result.response
- Multiple-choice
result.response
- Likert
result.response
- WAHTS CalibrationCheck
result.calibrationData
:- Frequency (Hz)
- Deviation from baseline (dB)
- MPANLS
result.mpanlsData
:- Frequency (Hz)
- Level (dB SPL)
- Limit (dB SPL--limit at this frequency)
- Attenuation (dB SPL--specified in protocol)
- Level under the WAHTS (dB SPL--level under the ear cup = level - att)
- Noise floor (dB SPL--dosimeter noise floor at this frequency)
- Multiple-input
result.response
for specified input fields - Three Digit Test:
- Ear
- Correct (boolean--whether all three digits were answered accurately)
- Response (digits selected)
- Current Digits (digits presented)
- Current Masker (presentation masker--positive or negative)
- Target Type (presentation target--filtered, timeCompressed, or H3CamFiltered)
- Digit Score (% of total number of digits correctly identified)
- Presentation Score (% of presentations where all 3 digits were correct)
- Current SNR (presentation SNR)
- Masker Level (dB SPL--presentation masker sound level)
- Target Level (dB SPL--presentation target sound level)
Results Schema
See JSON Schema Documentation for more info on how to use and read JSON Schema files.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "HFFD Exam Results Schema (unversioned)",
"required": ["protocolId", "protocolHash", "testResults"],
"properties": {
"buildName": {
"type": "string",
"description": "Unique identifier for the tabSINT build on the tablet reporting results."
},
"siteId": {
"type": "string",
"description": "Unique numerical site identifier where the exam was taken. This is converted to 'siteName' on the server."
},
"testDateTime": {
"type": "string",
"format": "date-time",
"description": "Date/time that the exam was started."
},
"qrString": {
"type": "string",
"description": "The string decoded from the QR code associated with the exam."
},
"gender": {
"enum": [ "m", "f"]
},
"age": {
"type": "integer"
},
"protocolId": {
"type": "string",
"description": "Unique numerical protocol id. This is converted to 'protocolName' on the server."
},
"protocolHash": {
"type": "string",
"description": "A unique hash identifying the protocol used to obtain these results."
},
"audiometryResults": {
"type": "object",
"description": "Results of audiometry testing as reported in QR code."
},
"nCorrect": {
"type": "number",
"description": "How many responses were correct?"
},
"nIncorrect": {
"type": "number",
"description": "How many responses were incorrect? (only 'false' responses are counted.)"
},
"nResponses": {
"type": "number",
"description": "How many total responses were there? (includes responses that are not right/wrong, such as questionnaire responses.)"
},
"testResults": {
"required": ["responses"],
"description": "JSON object containing any test results information not captured above. Is likely to contain fields not formally defined in this spec.",
"properties": {
"responses": {
"type": "array",
"items": {
"$ref": "#/definitions/response"
}
},
"softwareVersion": {
"properties": {
"version": {
"type": "string",
"description" : "The TabSINT software semantic version"
},
"date": {
"type": "string",
"description": "The TabSINT software build date"
},
"rev": {
"type": "string",
"description": "The TabSINT software revision number"
}
}
},
"tabletUUID":{
"type": "string",
"description": "The tablet unique identifier"
},
"tabletModel":{
"type": "string",
"description": "The tablet model"
},
"tabletLocation":{
"latitude": {
"type":"string",
"description":"latitude"
},
"longitude": {
"type":"string",
"description":"longitude"
}
},
"partialResults":{
"type":"boolean",
"description":"true if the exam was ended early and the results are partial"
}
}
}
},
"definitions": {
"response": {
"description": "Details of subject response to a single presentation.",
"properties": {
"presentationId": {
"type": "string",
"description": "Unique (w/in this exam) identifier for this presentation."
},
"response": {
"type": "string",
"description": "A string representing the response."
},
"correct": {
"type": "boolean",
"description": "True if this is the 'correct' response. False if it is incorrect. Undefined if this is not a right/wrong question."
},
"numberCorrect":{
"type": "number",
"description": "number of correct responses within a question. For example, 0-5 for OmtResponseArea"
},
"numberIncorrect":{
"type": "number",
"description": "number of incorrect responses within a question. For example, 0-5 for OmtResponseArea"
},
"eachCorrect":{
"type": "array",
"description": "Array. True/False if correct is set for that choice, null if correct is not defined."
},
"responseStartTime": {
"type": "string",
"format": "date-time",
"description": "Time that each question appears in standard format"
},
"responseElapTimeMS": {
"type": "number",
"description": "Response between question appearing and question being submitted, in milliseconds"
},
"notes": {
"type": "string",
"description": "Contains any warnings generated by the TabSINT program during execution of the page"
},
"otherResponse": {
"type": "string",
"description": "User-supplied input to the 'other' field of a checkbox response area"
},
"changedFields": {
"type": "object",
"description": "page fields modified by a functionRegistry function, called by the protocol for an individual page"
}
}
}
}
}
MATLAB Analysis Tool
A set of MATLAB functions to parse JSON results and isolate result fields have been developed to facilitate the analysis of TabSINT results. These functions work by taking the nested JSON results and flattening them into hierarchical data tables that are more easily analyzed.
Downloading the MATLAB Analysis Tool
Download the tools/matlab
directory from the TabSINT repository and unzip into a local folder. You can choose to work directly from this folder or you can add this folder to your MATLAB path (with subfolders). Wherever you do your analysis, you must be able to reference the MATLAB class TabsintResults
from the current active directory.
Importing and Parsing Results
Within MATLAB, change the current folder to a location that contains one or more JSON result files from TabSINT. The filenames of these results files don't matter as long as they have the file extension .json
.
The first step is to create an instance of the TabsintResults
class. We name this variable tr
, but you can choose any variable name you would like:
clear all;
tr = TabsintResults;
% type "help tr" to see class documentation for the `TabsintResults` class
help tr
The local variable tr
will contain methods to load, analyze, and output results.
After creating the variable tr
, run loadresults
to load all results in the current directory:
% type "help tr.loadresults" to see method documentation
help tr.loadresults
% load all individual results into a table
results = tr.loadresults();
% `results` table also set to class variable `tr.results`
tr.results
% view raw JSON results as MATLAB struct
tr.raw
The method tr.loadresults
parses all local JSON files and loads them into a struct array in tr.raw
.
Then the results in tr.raw
are lighly processed into a flattened table tr.results
.
Parsing Responses
After loading individual results, run loadresponses
to unpack each response from each results into a singular tabular dataset.
% type "help tr.loadresponses" to see method documentation
help tr.loadresponses
% load all responses from all results into a singular tabular dataset
responses = tr.loadresponses();
% `responses` table also set to class variable `tr.responses`
tr.responses
To load additional values from the JSON file response object, pass in a cell array of fields that match the keys in the in JSON file.
To access a nested field, use the .
notation (i.e. examProperties.OutputChannel
).
% unpack extra page or result fields into columns in the responses table
params = {'subjectId', 'examType', 'Ear', 'ResultType', ...
'Threshold', 'Units', 'F', 'L', 'RetSPL', ...
'FalsePositive','examProperties', 'examProperties.OutputChannel'};
% load all responses from all results into a singular tabular dataset with additional columns
responses = tr.loadresponses(params);
Test Specific Parsers
Parsing functions have been written for common response area types. The follow sections describe each specific type of parsing function:
Audiometry
Audiometry results can be loaded directly:
output = tr.loadaudiometry()
This will create the struct output
which will contain only audiometry results (generated by the Hughson-Westlake, Bekesy Like and Bekesy Highest Automated Frequency response areas).
output = tr.loadaudiometry() % load all audiometry tests
% output = tr.loadflft('BHAFT'); % load only BHAFT tests (adaptive)
Other result types can be investigated from the tr.responses
structure using either the appropriate presentationId
or examType
keys.
HINT
HINT results can be loaded directly:
output = tr.loadhint()
Custom Processing Functions
The TabSINT MATLAB tool supports arbitrary user-defined functions to encourage re-usable analysis code. This allows a user to write a processing function and share it with others using the TabSINT MATLAB tool.
See the demo function in the TabSINT repository for an example. Functions must be saved as .m
files in a local subdirectory ./functions
or accessible on the MATLAB path.
Use the runfunctions()
method to run custom functions.
% type "help tr.runfunctions" to see method documentation
help tr.runfunctions
% runs all functions in `./functions` subdirectory
output = tr.runfunctions();
% runs only the 'demo.m' function (must be in ./functions directory or on MATLAB path)
output = tr.runfunctions('demo');
Each function must take one input argument that refers to this TabsintResults class (i.e. tr
).
tr.results
is the results struct loaded in the method loadresults
.
tr.responses
is the responses struct loaded in the method loadresponses
.
tr.output
is a struct for the user to customize and save analysis results.
If a subdirectory ./functions
exists, this method will add this directory to the path.
Functions are evaluated in alphabetical order and MUST NOT begin with numerical characters.
Data Encryption
Tests results that are generated from a protocol containing a RSA public key are stored on the tablet and on Gitlab in .txt
base64 format.
Encryption Strategy
TabSINT uses hybrid encryption to encrypt data that has a RSA public key defined in the associated protocol. If no public key is provided, data is still encrypted within TabSINT, but is saved to the tablet and uploaded to Gitlab in its JSON or CSV unencrypted format. Hybrid encryption is simple, secure and widely used and accepted in cryptography. It combines the high security of RSA public-private asymmetric encryption and the efficiency of symmetric encryption. TabSINT uses the Advanced Encryption Standard (AES) as the symmetric encryption scheme, which was adopted by U.S. NIST in 2001 after thorough testing.
To encrypt TabSINT results:
- The protocol developer generates public private key pair
openssl rsa -pubout -in private_key.pem -out public_key.pem
- It is critical that the protocol generator saves the RSA private key and securely shares it with the result analyst. If the private key is lost, the data will be indecipherable.
- As TabSINT prepares result(s) for export to the tablet or upload to Gitlab, it encrypts result(s) with a randomly generated AES key (using the npm package
crypto-js
). - TabSINT encrypts the random AES key with the public key in the protocol (using the npm package
js-encrypt
). - When retrieving results, the results analyst can use a MATLAB tool to decrypt the random AES key with the private key and then decrypt the result(s) with the random AES key.
Encrypting and Decrypting Results
The MATLAB Analysis Tool has methods to:
- help the protocol developer generate private/public RSA key pairs, and
- decrypt results
To generate a private/public RSA key pair, create the TabsintResults
object, then use the generatekey()
method. Remember to save the private key carefully and securely. All results will be undecipherable without the private key.
clear all;
tr = TabsintResults;
tr.generatekey(); % generates private, public keys in current directory and loads public key text
publickey = tp.generatekey('tabsint.pem'); % generates specific private key `tabsint.pem` and loads public key text
Specify the publicKey
in the protocol.json
protocol file.
"title": "...",
...,
"publicKey": "enter public key here",
...,
"pages": [
To decrypt results generated by this protocol, create the TabsintResults
object, then use the decrypt()
method in the same directory as the encrypted results and private key.
clear all;
tr = TabsintResults;
tr.decrypt(); % by default uses any *.pem file in the current directory
tr.decrypt('tabsint.pem'); % specify filename of private key
Noise Measurement Data
Svantek Dosimeter
The Svantek Dosimeter SV104A has been integrated into TabsINT for recording background noise during TabSINT exams. Details of the implementation and basic usage can be found on the Dosimeter page.
Result Fields
Result Field | Data Type | Description | Units |
---|---|---|---|
time | String | Recording start time. | |
status | Integer | Status flag indicating 1/3 or 1/1 Octave band data. | |
Leq | Array | Mean level of each frequencies in the "Frequency" array over entire recording. | dB SPL |
Frequencies | Array | Band center frequencies of the reported spectral bands. | Hz |
LeqA | Float | A-weighted mean of Leq. | dB SPL |
LeqC | Float | C-weighted mean of Leq. | dB SPL |
LeqZ | Float | Mean of Leq using no spectral weighting. | dB SPL |
overallAmbientNoise | Float | Same as LeqA | dB SPL |
FBand | Integer | Center frequency of concurrent Exam. | Hz |
bandLevel | Float | Mean level of FBand frequency over recording duration. | dB SPL |
Sensimetric Sound Level Meter
A software plugin to measure sound pressure level and spectra from the Nexus 7 tablet has been integrated into TabSINT to record background noise data.
Result Fields
Result Field | Data Type | Description | Units |
---|---|---|---|
recordingStartTime | String | Recording start time. | |
recordingDuration | String | Recording duration. | Seconds |
numberOfReports | String | Number of reported time points, equal to the number of reported SPL values and number of rows in reported spectra. | |
timePoints | String | List of time points. | Seconds |
SPL_A_mean | String | Time series of A-weighted mean sound pressure level. | dB SPL |
meanSpectrum | String | A 22-band spectrum (100-12500 Hz) of mean level for each time interval. | dB SPL |
peakSpectrum | String | A 22-band spectrum (100-12500 Hz) of peak level for each time interval. | dB SPL |
SPL_A_slow | String | Returns output of an exponential filter with a 1000-ms time constant at the end of the reporting interval using the A-weighted SPL. | dB SPL |
bandCenterFrequencies | String | List of the center frequencies of the reported spectral bands. | Hz |
Frequencies | Array | List of center frequencies as an array. | Hz |
Leq | Array | Mean level of each frequencies in the "Frequencies" array over entire recording. | dB SPL |
LeqA | Float | A-weighted mean of Leq. | dB SPL |
overallAmbientNoise | Float | Same as LeqA. | dB SPL |
FBand | Integer | Center frequency of concurrent Hughson-Westlake Exam. | Hz |
bandLevel | Float | Mean level of FBand frequency over recording duration. | dB SPL |
Unity Games run from TabSINT
TabSINT protocols can be configured to run the following games as part of a protocol:
- Fetch
- Computro
These games train the subject to better understand speech in noise, and a subject's performance in the game is related to how well they understand speech in noise.
The games are run from TabSINT as response areas.
Fetch Response Area
Used to load Fetch game from TabSINT. This page typically does not require user interaction, it is used to define the parameters involved in running Fetch.
Protocol Example
{
"id": "Fetch",
"title": "Launch Fetch",
"questionMainText": "Launching Fetch Game",
"responseArea": {
"type": "externalAppResponseArea",
"appName": "com.creare.fetch"
}
}
Options
autoSubmit
:- Type:
boolean
- Description: If
true
, go straight to next page once this page is complete. (Default =false
)
- Type:
appName
:- Type:
string
- Description: Package name for fetch (
com.creare.fetch
).
- Type:
dataOut
:Type:
object
Description: Object containing the following options:
message
:- Type:
string
- Description: A string message to pass to external app - this could be something telling the external app what to do.
- Type:
data
:Type:
string
Description: Open ended field to pass other data to the external app, such as a number. This field may contain the following objects.
PerpetualPlay
:- Type:
boolean
- Description: Deprecated. Please use NumLevelsToPlay = -1. (Default =
true
)
- Type:
StartLevelNum
:- Type:
number
- Description: Unity level to start on. (Default= 1)
- Type:
MostDifficultLevel
:- Type:
number
- Description: Most difficult Unity level. (Default= 40)
- Type:
NumLevelsToPlay
:- Type:
number
- Description: Number of Fetch levels to play, after which the Unity application will transfer back to TabSINT automatically. If -1, then Fetch will continue to play indefinitely. (Default= -1)
- Type:
MinBikeSpeed
:- Type:
number
- Description: Minimum Unity Fetch Game bike speed. (Default= 3)
- Type:
MaxBikeSpeed
:- Type:
number
- Description: Maximum Unity Fetch Game bike speed. (Default= 8)
- Type:
MinTailSpeed
:- Type:
number
- Description: Minimum Unity Fetch Game tail speed. (Default= 3.5)
- Type:
MaxTailSpeed
:- Type:
number
- Description: Maximum Unity Fetch Game tail speed. (Default= 8.5)
- Type:
EasiestSnrDb
:- Type:
number
- Description: Easiest (maximum) Unity SNR (dB). (Default= 6)
- Type:
HardestSnrDb
:- Type:
number
- Description: Most difficult (minimum) Unity SNR (dB). (Default= -20)
- Type:
MinAmbientVol
:- Type:
number
- Description: Minimum ambient volume (dB). (Default= 0.2)
- Type:
MaxAmbientVol
:- Type:
number
- Description: Maximum ambient volume (dB). (Default= 0.5)
- Type:
MinLevelLengthTurns
:- Type:
number
- Description: Number of audio cues (turns) the player must correctly decipher to win level 0. (Default= 15)
- Type:
MaxLevelLengthTurns
:- Type:
number
- Description: Number of audio cues (turns) the player must correctly decipher to win the most difficult level. (Default= 30)
- Type:
Computro Response Area
Used to load Computro game from TabSINT. This page typically does not require user interaction, it is used to define the parameters involved in running Computro.
Protocol Example
{
"id": "Computro",
"title": "Launch Computro",
"questionMainText": "Launching Computro Game",
"responseArea": {
"type": "externalAppResponseArea",
"appName": "com.creare.computro"
}
}
Options
autoSubmit
:- Type:
boolean
- Description: If
true
, go straight to next page once this page is complete. (Default =false
)
- Type:
appName
:- Type:
string
- Description: Package name for computro (
com.creare.computro
).
- Type:
dataOut
:Type:
object
Description: Object containing the following options.
message
:- Type:
string
- Description: A string message to pass to external app - this could be something telling the external app what to do.
- Type:
data
:Type:
string
Description: Open ended field to pass other data to the external app, such as a number. This field may contain the following objects.
levels
:Type:
array
Description: Array which may contain the following objects for each level of play.
playbackRate
:- Type:
number
- Description: Speed multiplier for the target audio. Must be nonzero. Recommended range is 0.5 (half speed) to 2.0 (double speed). (Default= 1)
- Type:
SpiesCaughtBeforeLevel
:- Type:
number
- Description: Unity level to start on. (Default= 0)
- Type:
NumDecodeTries
:- Type:
number
- Description: Number of trials a player has to decode a message before declaring that the player has lost the level. (Default= 3) "default": 65
- Type:
signalSPL
:- Type:
number
- Description: Volume at which to play the 'target' sound - the radio program recordings (dB SPL). Only effective if externalTargetAudioPath is defined and signalType=1. (Default= 65)
- Type:
maskerSPL
:- Type:
number
- Description: "Volume at which to play the masker sound (db SPL). Set to zero for no masker. Only effective if maskerAudioPath is defined and targetType=1. (Default= 65)
- Type:
rewardName
:- Type:
string
- Description: Type of reward to show the player. Sound rewards (coffeeMaker, fan, radio) replace any previous masker. Visual rewards (rock, pencilHolder, picture, plant, mug, tchotchke) accumulate on the Unity 'desk'. If this parameter is not specified in the protocol, TabSINT will choose one at random.", "enum": ["none", "coffeeMaker", "fan", "mug", "pencilHolder", "picture", "plant", "radio", "rock", "tchotchke"]
- Type:
wordMaxLateTimeS
:- Type:
number
- Description: If the player selects a word this many seconds after the word ends in the audio recording, it is scored as incorrect. (Default= 4)
- Type:
wordMaxEarlyTimeS
:- Type:
number
- Description: If the player selects a word this many seconds before the word begins in the audio recording, it is scored as incorrect. The time of each word in the recording may be estimated, rather than precisely known. This setting exists to add tolerance for the mismatch. (Default= 1)
- Type:
wordAdvanceSelTimeS
:- Type:
number
- Description: Maximum duration, in seconds, a word can be presented and selected on the screen before it is spoken in the clip. (Default= 10)
- Type:
JSON results format common to all games
A subject's performance in the game is related to how well they understand speech in noise. Their performance is captured in the JSON-formatted TabSINT results.
The games are run from TabSINT as response areas, and thus, results from a game are another type of response.
The response structure for a game will look like this:
"response": {
"message": "This is data from <game name>",
"data": {
<game result data>
}
}
The specific format of the game result data will vary based on the game.
Fetch results format
An example Fetch result is shown below, with repetitions omitted for brevity. Discussion of fields follows.
"response": {
"message": "This is data from Fetch",
"data": [{
"levelNum": 0,
"challengeSettings": {
"turns": 30,
"bikeSpeed": 6,
"tailSpeed": 0.5,
"maskerVolume": 0,
"ambientSoundVolume": 0
},
"levelEndReason": 0,
"livesAtStart": 3,
"turns": [{
"spokenStreetName": "ZULU",
"turnChoices": ["QUEBEC", "ZULU"],
"userChosenStreetName": "ZULU",
"timeFromCueToChoice": 1.3077239990234375,
"advanceDistanceChoiceMade": 0.8392735719680786,
"madeCorrectChoice": true
},
... Each level consists of many turns ...
]
},
... Each game includes several levels ...
]
}
levelNum
Zero-indexed number of the level represented below.
challengeSettings
A group containing the challenges presented to the player based on the configuration and the level number.
turns
The number of times the user is presented with an audio cue and a choice of two streets.
bikeSpeed
How fast the player's character moves through the streets this level. Higher numbers require better reaction time from the user.
tailSpeed
When the player gives the wrong answer, an enemy "tail" car appears to chase the player character. This is the speed at which that car is traveling this level.
maskerVolume
The playback volume of the masker audio, between 0.0 and 1.0.
ambientSoundVolume
The playback volume of the ambient flavor sounds ("street" noises). Between 0.0 and 1.0.
levelEndReason
The reason this level ended. 0 indicates the user won the level, and 1 indicates the user was "caught" and lost the level.
livesAtStart
The number of lives the user started this level with. They begin the game with 3 lives.
turns
A list of the turns the user was presented with during this level.
spokenStreetName
The target audio spoken to the player, with the correct street name.
turnChoices
The options presented to the user to choose from.
userChosenStreetName
The street name the user chose.
timeFromCueToChoice
The player's reaction time, from the end of the target audio to the time the user tapped the street name.
advanceDistanceChoiceMade
How far away (in game units) the player character was from the intersection when the user tapped a street name.
madeCorrectChoice
true
if the user chose the correct street name, or false
otherwise.
Computro results format
An example Computro result is shown below, with repetitions omitted for brevity. Discussion of fields follows.
"response": {
"message": "This is data from Computro",
"data": {
"levels": [{
"clips": [{
"targetAudioName": "63",
"wordPairs": [{
"leftWord": {
"start": 4.739999771118164,
"stop": 5.150000095367432,
"content": "study"
},
"rightWord": {
"start": 8.399999618530273,
"stop": 8.960000038146973,
"content": "sides"
},
"userSelectedWord": {
"start": 4.739999771118164,
"stop": 5.150000095367432,
"content": "study"
},
"scoredAsCorrect": true,
"timedOut": false,
"timeStart": 9.742508888244629,
"timeEnd": 14.760058403015137,
"timeEndInClip": 6.9120001792907715,
"responseTime": 1.7620000839233398
}
... Each clip will feature many word pairs ...
]
}
... There may be more than one clip per level ...
],
"activeSettings": {
"playbackRate": 1.25,
"signalVolume": 1,
"maskerVolume": 0.5,
"rewardName": "tchotchke",
"wordMaxLateTimeS": 4,
"wordMaxEarlyTimeS": 1,
"minWordSeparationTimeS": 0.75,
"wordAdvanceSelTimeS": 10
}
}
... A game may include more than one level ...
]
}
}
levels
A game of Computro can be configured to run for any number of levels. Each level can have a different set of settings. The settings for a particular level are recorded in the activeSettings
field.
clips
In each level of Computro, the user is given unlimited chances to "decode" a "secret message". Each such attempt consists of an audio clip played back to the user, typically from an old radio program.
targetAudioName
The name of the audio clip played back to the user.
wordPairs
Computro displays two words to the user. When the user hears a word, the user clicks one, and it is replaced by another word, resulting in a new unique pair of words. A new pair can also be created when a user misses a word, and the word times out automatically.
Each entry in the wordPairs
array represents one such unique pair of words displayed to the user.
leftWord
, rightWord
, userSelectedWord
The words displayed on the left and right sides of Computro, and the word that the user selected to end the pair. If timedOut
is true
, then userSelectedWord
will contain nonsense.
start
and stop
indicate the time, in seconds relative to the start of the clip, that the audio of the word started and stopped. content
indicates the text of the word.
scoredAsCorrect
true
if the user was told they selected the correct word for this word pair. false
if they chose a word that hadn't appeared yet, or if this word pair ended with a timeout.
timedOut
If true
, then one of the words timed out before the user selected a word.
timeStart
, timeEnd
Indicates the time this word pair started and ended, in seconds since the game was started. Each word pair ends when either the user selects a word, or a word times out and is removed from the screen.
timeEndInClip
Same as timeEnd
, but indicates how many seconds of audio have elapsed rather than how many seconds of the game have elapsed. This puts it in the same units as start
and stop
for each word, so you can see how the user's action lines up with nearby words.
responseTime
Time, in seconds, between the end of a word in the target audio and the user selecting that word. Will be invalid if timedOut
is true
.
activeSettings
A copy of the settings structure provided to Computro for this level. Represents the settings active during the level.
playerWon
Whether the player won the current level.