compileprofile-spacetests 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CLAUDE.md +115 -0
  2. package/README.md +147 -34
  3. package/dist/cjs/common-interfaces.d.ts +60 -0
  4. package/dist/cjs/common-interfaces.js +2 -0
  5. package/dist/cjs/emotions.d.ts +2 -7
  6. package/dist/cjs/emotions.js +56 -22
  7. package/dist/cjs/gonogo.d.ts +1 -6
  8. package/dist/cjs/gonogo.js +61 -14
  9. package/dist/cjs/index.d.ts +2 -5
  10. package/dist/cjs/nback.d.ts +1 -11
  11. package/dist/cjs/nback.js +27 -13
  12. package/dist/cjs/spatial-cognition.d.ts +1 -6
  13. package/dist/cjs/spatial-cognition.js +69 -14
  14. package/dist/esm/common-interfaces.d.ts +60 -0
  15. package/dist/esm/common-interfaces.js +1 -0
  16. package/dist/esm/emotions.d.ts +2 -7
  17. package/dist/esm/emotions.js +55 -21
  18. package/dist/esm/gonogo.d.ts +1 -6
  19. package/dist/esm/gonogo.js +61 -14
  20. package/dist/esm/index.d.ts +2 -5
  21. package/dist/esm/nback.d.ts +1 -11
  22. package/dist/esm/nback.js +27 -13
  23. package/dist/esm/spatial-cognition.d.ts +1 -6
  24. package/dist/esm/spatial-cognition.js +69 -14
  25. package/example-data/emotions.json +807 -807
  26. package/example-data/gonogo.json +5392 -5392
  27. package/example-data/nback.json +892 -892
  28. package/example-data/participant.json +6 -6
  29. package/example-data/spatial-cognition.json +462 -462
  30. package/jest.config.js +13 -13
  31. package/original/emotion-recognition.R +39 -39
  32. package/original/gonogo.R +32 -32
  33. package/package.json +40 -40
  34. package/src/__tests__/integration/browserInfo.test.ts +16 -16
  35. package/src/__tests__/integration/emotions.test.ts +172 -64
  36. package/src/__tests__/integration/gonogo.test.ts +183 -80
  37. package/src/__tests__/integration/nback.test.ts +148 -55
  38. package/src/__tests__/integration/spatial-cognition.test.ts +171 -66
  39. package/src/__tests__/test-utils/testData.ts +79 -79
  40. package/src/common-interfaces.ts +79 -0
  41. package/src/emotions.ts +98 -59
  42. package/src/getters.ts +21 -21
  43. package/src/gonogo.ts +126 -75
  44. package/src/index.ts +39 -23
  45. package/src/nback.ts +61 -53
  46. package/src/spatial-cognition.ts +112 -54
  47. package/tsconfig.cjs.json +12 -12
  48. package/tsconfig.esm.json +14 -14
package/CLAUDE.md ADDED
@@ -0,0 +1,115 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is a TypeScript package that evaluates cognitive test results from "Vzhuru do vesmiru" (To Space) cognitive testing platform. The package analyzes performance data from four different cognitive tests: N-back memory tests, spatial cognition tests, Go/No-Go response inhibition tests, and emotion recognition tests.
8
+
9
+ ## Build Commands
10
+
11
+ - `npm run build` - Build both CommonJS and ESM distributions
12
+ - `npm run build:csj` - Build CommonJS distribution only
13
+ - `npm run build:esm` - Build ESM distribution only
14
+ - `npm test` - Run all tests using Jest
15
+ - `npm run prepare` - Automatically builds before publishing
16
+
17
+ ## Testing
18
+
19
+ - Jest is configured with TypeScript support
20
+ - Test files should follow patterns: `**/__tests__/**/*.ts` or `**/?(*.)+(spec|test).ts`
21
+ - Tests are located in `src/__tests__/integration/`
22
+ - Test utilities and shared data are in `src/__tests__/test-utils/`
23
+ - Run single test: `npm test -- --testNamePattern="test_name"`
24
+ - Run tests for specific file: `npm test -- emotions.test.ts`
25
+
26
+ ## Architecture
27
+
28
+ ### Core Structure
29
+
30
+ The package exports four main calculation functions from `src/index.ts`:
31
+ - `NbackResults(data)` - Analyzes N-back memory test performance
32
+ - `SpatialCognitionResults(data)` - Evaluates spatial cognition test results
33
+ - `GonogoResults(data)` - Processes Go/No-Go inhibition test data
34
+ - `EmotionResults(data)` - Analyzes emotion recognition test performance
35
+
36
+ ### Data Processing Pipeline
37
+
38
+ Each cognitive test follows a consistent three-step processing pattern:
39
+
40
+ 1. **Extract Trials**: Filter raw test data to identify relevant trial records
41
+ - `nback_extract_trials()` - Filters for records with `is_target` field
42
+ - `spatial_extract_trials()` - Filters for records with image stimulus data
43
+ - `gonogo_extract_trials()` - Filters for records with image responses
44
+ - `emotion_extract_trials()` - Filters for records with emotion response data
45
+
46
+ 2. **Calculate Results**: Compute accuracy, reaction time, and derived metrics
47
+ - All tests calculate: trial count (`n`), average accuracy (`avg_acc`), average reaction time (`avg_rt`)
48
+ - Each test has specific performance scoring algorithms
49
+
50
+ - the results should have a uniform structure
51
+ - common - should be common structure for all tests
52
+ - n_trials (number of trials)
53
+ - n_correct_trials (number of correct trials)
54
+ - n_incorrect_trials (number of incorrect trials)
55
+ - n_missing_trials (number of missing trials)
56
+ - avg_rt_total (in ms)
57
+ - avg_rt_correct (in ms)
58
+ - avg_rt_incorrect (in ms)
59
+ - avg_rt_missing (in ms)
60
+ - performance_score - score calculated as per test instruction - differs for each test slightly
61
+ - special - special results inherent for the test itself
62
+
63
+ 3. **Performance Scoring**: Convert raw metrics to normalized 0-100 performance scores
64
+ - Go/No-Go: Uses RT/(accuracy^5) with 300-5000ms bounds
65
+ - Emotions: Uses RT/(accuracy^5) with 1000-10000ms bounds
66
+ - Spatial: Uses RT/accuracy with 1000-10000ms bounds
67
+ - N-back: Uses raw accuracy as performance score
68
+
69
+ ### Key Implementation Details
70
+
71
+ **N-back Test** (`src/nback.ts`):
72
+ - Processes target vs non-target trials separately
73
+ - Returns comprehensive breakdown of both trial types
74
+ - Performance score is simply average accuracy
75
+
76
+ **Spatial Cognition Test** (`src/spatial-cognition.ts`):
77
+ - Extracts map direction (left/right), distance, angle, and rotation from image URLs
78
+ - Compares user response direction against correct answer
79
+ - Uses simpler RT/accuracy performance formula
80
+
81
+ **Go/No-Go Test** (`src/gonogo.ts`):
82
+ - Determines correct response based on block number and stimulus type
83
+ - Block 1: respond to astronaut, Block 2: respond to alien, Block 3: respond to rocket, Block 4: respond to non-rocket
84
+ - Extracts stimulus type from image URL patterns
85
+
86
+ **Emotion Recognition Test** (`src/emotions.ts`):
87
+ - Maps numeric responses (0-4) to emotion labels: neutral, sad, happy, surprised, angry
88
+ - Extracts emotion type and image number from file paths
89
+ - Compares recognized emotion against correct emotion
90
+
91
+ ### Data Formats
92
+
93
+ All tests expect arrays of trial objects with specific fields:
94
+ - N-back: `is_target`, `rt`, `correct`
95
+ - Spatial: `stimulus` (HTML img tag), `response`, `rt`
96
+ - Go/No-Go: `image` (URL), `response`, `rt`, `block_number`
97
+ - Emotions: `emotion` (URL), `response`, `rt`
98
+
99
+ ## Utilities
100
+
101
+ **Browser Information** (`src/getters.ts`):
102
+ - `getBrowserInformation(data)` extracts browser/system info from test data
103
+ - Returns OS, browser version, screen dimensions, hardware capabilities
104
+
105
+ **Normative Data** (`src/norms/`):
106
+ - JSON files contain normative performance data for each test type
107
+ - Used for percentile calculations and age/gender adjustments
108
+
109
+ ## Development Notes
110
+
111
+ - Package supports both CommonJS and ESM exports
112
+ - TypeScript configurations: `tsconfig.cjs.json` and `tsconfig.esm.json`
113
+ - All calculation functions include comprehensive TypeScript interfaces
114
+ - Console logging is used in some functions for debugging
115
+ - Error handling throws descriptive errors for empty trial datasets
package/README.md CHANGED
@@ -1,35 +1,148 @@
1
- # compileprofile-spacetests
2
-
3
- A package for evaluating cognitive test results, specifically designed for memory tests.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install compileprofile-spacetests
9
- ```
10
-
11
- ## Usage
12
-
13
- ```typescript
14
- import { evaluateMemoryTest, MemoryTestData, SubjectParameters } from 'compileprofile-spacetests';
15
- // Evaluate the test results
16
- const results = evaluateMemoryTest(testData, subjectParams);
17
- console.log(results);
18
- ```
19
-
20
-
21
- ## Development
22
-
23
- Basic js distribution
24
-
25
- ## API
26
-
27
- Evaluates memory test results and returns a comprehensive analysis including:
28
- - Overall accuracy
29
- - Average reaction time
30
- - Total correct responses
31
- - Total number of trials
32
- - Age-adjusted score (for subjects between 18-65)
33
- - Gender-specific percentile (when gender is specified)
34
-
1
+ # compileprofile-spacetests
2
+
3
+ A package for evaluating cognitive test results from "Vzhuru do vesmiru" (To Space) cognitive testing platform. This package analyzes performance data from four different cognitive tests: N-back memory tests, spatial cognition tests, Go/No-Go response inhibition tests, and emotion recognition tests.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install compileprofile-spacetests
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import {
15
+ NbackResults,
16
+ SpatialCognitionResults,
17
+ GonogoResults,
18
+ EmotionResults
19
+ } from 'compileprofile-spacetests';
20
+
21
+ // Analyze N-back memory test
22
+ const nbackResults = NbackResults(nbackData);
23
+
24
+ // Analyze spatial cognition test
25
+ const spatialResults = SpatialCognitionResults(spatialData);
26
+
27
+ // Analyze Go/No-Go test
28
+ const gonogoResults = GonogoResults(gonogoData);
29
+
30
+ // Analyze emotion recognition test
31
+ const emotionResults = EmotionResults(emotionData);
32
+ ```
33
+
34
+ ## Test Results
35
+
36
+ All cognitive tests return results in two parts: **common metrics** (same for all tests) and **special metrics** (specific to each test type).
37
+
38
+ ### Common Metrics (All Tests)
39
+
40
+ Every test provides these basic performance measures:
41
+
42
+ - **n_trials** - Total number of test trials completed
43
+ - **n_correct_trials** - How many responses were correct
44
+ - **n_incorrect_trials** - How many responses were wrong
45
+ - **avg_rt_total** - Average reaction time across all trials (milliseconds)
46
+ - **avg_rt_correct** - Average reaction time for correct answers only
47
+ - **avg_rt_incorrect** - Average reaction time for wrong answers only
48
+ - **performance_score** - Overall performance score (0-100, higher is better)
49
+
50
+ ### Special Metrics by Test Type
51
+
52
+ #### N-back Memory Test
53
+
54
+ Analyzes working memory by comparing performance on different trial types:
55
+
56
+ - **target_trials** - Performance when participant should respond (saw matching stimulus)
57
+ - Number of target trials, average reaction time, accuracy rate
58
+ - **non_target_trials** - Performance when participant should not respond
59
+ - Number of non-target trials, average reaction time, accuracy rate
60
+
61
+ #### Spatial Cognition Test
62
+
63
+ Analyzes spatial reasoning by breaking down performance across map characteristics:
64
+
65
+ - **by_distance** - Performance grouped by how far the destination is (1, 2, 3 units)
66
+ - **by_angle** - Performance grouped by map rotation angle (90°, 180°, 270°)
67
+ - **by_rotation** - Performance grouped by how much the view was rotated
68
+
69
+ Each group shows number of trials, average reaction time, and accuracy rate.
70
+
71
+ #### Go/No-Go Response Inhibition Test
72
+
73
+ Analyzes impulse control by examining when to respond vs. when to inhibit:
74
+
75
+ - **by_block** - Performance in each test phase (blocks 1-4 have different rules)
76
+ - **go_trials** - Trials where participant should press the button
77
+ - Number of trials, average reaction time, accuracy rate
78
+ - **nogo_trials** - Trials where participant should NOT press the button
79
+ - Number of trials, average reaction time, accuracy rate
80
+
81
+ #### Emotion Recognition Test
82
+
83
+ Analyzes emotion processing by examining recognition patterns:
84
+
85
+ - **by_emotion** - Performance for each emotion type (neutral, sad, happy, surprised, angry)
86
+ - For each emotion: number of trials, average reaction time, accuracy rate
87
+ - **confusion_matrix** - Shows which emotions get confused with which others
88
+ - Rows = actual emotion, columns = what participant guessed
89
+
90
+ ## Performance Scoring
91
+
92
+ Each test uses a specific algorithm to calculate the performance score (0-100):
93
+
94
+ - **N-back**: Raw accuracy percentage
95
+ - **Spatial Cognition**: RT/(accuracy) formula with 1000-10000ms bounds
96
+ - **Go/No-Go**: RT/(accuracy^5) formula with 300-5000ms bounds
97
+ - **Emotions**: RT/(accuracy^5) formula with 1000-10000ms bounds
98
+
99
+ ## Input Data Format
100
+
101
+ Each test expects an array of trial objects with specific fields:
102
+
103
+ ### N-back Test Data
104
+
105
+ Each trial object should have:
106
+ - **is_target** - `true` if participant should respond, `false` if they shouldn't
107
+ - **rt** - Reaction time in milliseconds
108
+ - **correct** - `true` if response was correct, `false` if wrong
109
+ - **response** - What the participant pressed (0 or 1, or null if no response)
110
+
111
+ ### Spatial Cognition Test Data
112
+
113
+ Each trial object should have:
114
+ - **stimulus** - HTML image tag containing the map image
115
+ - **rt** - Reaction time in milliseconds
116
+ - **response** - Direction chosen (0 = left, 1 = right)
117
+
118
+ ### Go/No-Go Test Data
119
+
120
+ Each trial object should have:
121
+ - **image** - URL to the stimulus image (astronaut, alien, or rocket)
122
+ - **rt** - Reaction time in milliseconds
123
+ - **response** - Button press (any number = pressed, null = no press)
124
+ - **block_number** - Which test phase (1, 2, 3, or 4)
125
+
126
+ ### Emotion Recognition Test Data
127
+
128
+ Each trial object should have:
129
+ - **emotion** - URL to the emotion face image
130
+ - **rt** - Reaction time in milliseconds
131
+ - **response** - Emotion chosen (0=neutral, 1=sad, 2=happy, 3=surprised, 4=angry)
132
+
133
+ ## Development
134
+
135
+ Build the package:
136
+ ```bash
137
+ npm run build # Build both CommonJS and ESM
138
+ npm run build:cjs # Build CommonJS only
139
+ npm run build:esm # Build ESM only
140
+ ```
141
+
142
+ Run tests:
143
+ ```bash
144
+ npm test # Run all tests
145
+ npm test -- emotions.test.ts # Run specific test file
146
+ ```
147
+
35
148
  ## License
@@ -0,0 +1,60 @@
1
+ interface CommonResults {
2
+ n_trials: number;
3
+ n_correct_trials: number;
4
+ n_incorrect_trials: number;
5
+ avg_rt_total: number;
6
+ avg_rt_correct: number;
7
+ avg_rt_incorrect: number;
8
+ performance_score: number;
9
+ }
10
+ interface NbackSpecialResults {
11
+ target_trials: {
12
+ n: number;
13
+ avg_rt: number;
14
+ avg_acc: number;
15
+ };
16
+ non_target_trials: {
17
+ n: number;
18
+ avg_rt: number;
19
+ avg_acc: number;
20
+ };
21
+ }
22
+ interface SpatialSpecialResults {
23
+ by_distance: any[];
24
+ by_angle: any[];
25
+ by_rotation: any[];
26
+ }
27
+ interface GonogoSpecialResults {
28
+ by_block: any[];
29
+ go_trials: {
30
+ n: number;
31
+ avg_rt: number;
32
+ avg_acc: number;
33
+ };
34
+ nogo_trials: {
35
+ n: number;
36
+ avg_rt: number;
37
+ avg_acc: number;
38
+ };
39
+ }
40
+ interface EmotionSpecialResults {
41
+ by_emotion: any[];
42
+ confusion_matrix: any;
43
+ }
44
+ interface NbackResultsStructure {
45
+ common: CommonResults;
46
+ special: NbackSpecialResults;
47
+ }
48
+ interface SpatialResultsStructure {
49
+ common: CommonResults;
50
+ special: SpatialSpecialResults;
51
+ }
52
+ interface GonogoResultsStructure {
53
+ common: CommonResults;
54
+ special: GonogoSpecialResults;
55
+ }
56
+ interface EmotionResultsStructure {
57
+ common: CommonResults;
58
+ special: EmotionSpecialResults;
59
+ }
60
+ export { CommonResults, NbackResultsStructure, SpatialResultsStructure, GonogoResultsStructure, EmotionResultsStructure, NbackSpecialResults, SpatialSpecialResults, GonogoSpecialResults, EmotionSpecialResults };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,10 +1,5 @@
1
- interface EmotionResultsStructure {
2
- n: number;
3
- avg_rt: number;
4
- avg_acc: number;
5
- performance: number;
6
- }
1
+ import { EmotionResultsStructure } from './common-interfaces';
7
2
  declare const emotion_calculate_results: (obj: any[]) => EmotionResultsStructure;
8
- declare const emotion_results: (obj: any[]) => EmotionResultsStructure;
9
3
  declare const emotion_extract_trials: (obj: any[]) => any[];
4
+ declare const emotion_results: (obj: any[]) => EmotionResultsStructure;
10
5
  export { EmotionResultsStructure, emotion_calculate_results, emotion_extract_trials, emotion_results };
@@ -1,36 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.emotion_results = exports.emotion_extract_trials = exports.emotion_calculate_results = void 0;
4
+ var EMOTION_MAP = ["neutral", "sad", "happy", "surprised", "angry"];
4
5
  var emotion_calculate_results = function (obj) {
5
6
  var trials = emotion_extract_trials(obj);
6
- // throw if trials is empty
7
7
  if (trials.length === 0) {
8
8
  throw new Error("No trials found");
9
9
  }
10
10
  return emotion_results(trials);
11
11
  };
12
12
  exports.emotion_calculate_results = emotion_calculate_results;
13
- var emotion_results = function (obj) {
14
- // throw error if obj is empty
15
- if (obj.length === 0) {
16
- throw new Error("No trials found");
17
- }
18
- var results = {
19
- n: obj.length,
20
- avg_rt: obj.reduce(function (a, b) { return a + b.rt; }, 0) / obj.length,
21
- avg_acc: obj.reduce(function (a, b) { return a + b.correct; }, 0) / obj.length,
22
- performance: NaN
23
- };
24
- var best_score = 1000;
25
- var worst_score = 10000;
26
- var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
27
- performance = Math.min(Math.max(performance, best_score), worst_score);
28
- results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
29
- return results;
30
- };
31
- exports.emotion_results = emotion_results;
32
13
  var emotion_extract_trials = function (obj) {
33
- var emotionMap = ["neutral", "sad", "happy", "surprised", "angry"];
34
14
  // filter trials where response and rt are defined and not null
35
15
  var trials = obj.filter(function (o) { return 'response' in o && 'rt' in o && 'emotion' in o; });
36
16
  trials = trials.filter(function (o) { return o.response !== null && o.rt !== null; });
@@ -45,10 +25,64 @@ var emotion_extract_trials = function (obj) {
45
25
  }
46
26
  });
47
27
  trials.forEach(function (o) {
48
- o.emotion_response = emotionMap[o.response] || "unknown";
28
+ o.emotion_response = EMOTION_MAP[o.response] || "unknown";
49
29
  o.correct = o.emotion === o.emotion_response;
50
30
  // in the older ones there were 15 trials per rotation
51
31
  });
52
32
  return trials;
53
33
  };
54
34
  exports.emotion_extract_trials = emotion_extract_trials;
35
+ var emotion_results = function (obj) {
36
+ if (obj.length === 0) {
37
+ throw new Error("No trials found");
38
+ }
39
+ var correct_trials = obj.filter(function (o) { return o.correct === true; });
40
+ var incorrect_trials = obj.filter(function (o) { return o.correct === false; });
41
+ var total_rt = obj.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
42
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
43
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
44
+ var avg_rt = total_rt / obj.length;
45
+ var avg_acc = correct_trials.length / obj.length;
46
+ // Calculate performance score using the existing formula
47
+ var best_score = 1000;
48
+ var worst_score = 10000;
49
+ var performance = avg_rt / (Math.pow(avg_acc, 5) + 0.001);
50
+ performance = Math.min(Math.max(performance, best_score), worst_score);
51
+ var performance_score = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
52
+ var common = {
53
+ n_trials: obj.length,
54
+ n_correct_trials: correct_trials.length,
55
+ n_incorrect_trials: incorrect_trials.length,
56
+ avg_rt_total: avg_rt,
57
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_trials.length : 0,
58
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_trials.length : 0,
59
+ performance_score: performance_score
60
+ };
61
+ // Group by emotion for special results
62
+ var by_emotion = EMOTION_MAP.map(function (emotion) {
63
+ var emotion_trials = obj.filter(function (o) { return o.emotion === emotion; });
64
+ return {
65
+ emotion: emotion,
66
+ n: emotion_trials.length,
67
+ avg_rt: emotion_trials.length > 0 ? emotion_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / emotion_trials.length : 0,
68
+ avg_acc: emotion_trials.length > 0 ? emotion_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / emotion_trials.length : 0,
69
+ };
70
+ });
71
+ // Create confusion matrix
72
+ var confusion_matrix = EMOTION_MAP.reduce(function (matrix, actual) {
73
+ matrix[actual] = EMOTION_MAP.reduce(function (row, predicted) {
74
+ row[predicted] = obj.filter(function (o) { return o.emotion === actual && o.emotion_response === predicted; }).length;
75
+ return row;
76
+ }, {});
77
+ return matrix;
78
+ }, {});
79
+ var special = {
80
+ by_emotion: by_emotion,
81
+ confusion_matrix: confusion_matrix
82
+ };
83
+ return {
84
+ common: common,
85
+ special: special
86
+ };
87
+ };
88
+ exports.emotion_results = emotion_results;
@@ -1,9 +1,4 @@
1
- interface GonogoResultsStructure {
2
- n: number;
3
- avg_rt: number;
4
- avg_acc: number;
5
- performance: number;
6
- }
1
+ import { GonogoResultsStructure } from './common-interfaces';
7
2
  declare const gonogo_calculate_results: (data: any[]) => GonogoResultsStructure;
8
3
  declare const gonogo_extract_trials: (obj: any[]) => any[];
9
4
  declare const gonogo_results: (data: any[]) => GonogoResultsStructure;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.gonogo_results = exports.gonogo_extract_trials = exports.gonogo_calculate_results = void 0;
4
+ var BEST_SCORE = 300;
5
+ var WORST_SCORE = 5000;
4
6
  var gonogo_calculate_results = function (data) {
5
7
  var trials = gonogo_extract_trials(data);
6
8
  var results = gonogo_results(trials);
@@ -12,9 +14,7 @@ var gonogo_extract_trials = function (obj) {
12
14
  var trials = obj.filter(function (o) { return 'image' in o && o.image !== undefined; });
13
15
  trials.forEach(function (o) {
14
16
  // image is in format <stimulus>_trans_<number>.png
15
- // extract the stimulus and number
16
17
  // "image": "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/astronaut_trans_1.png",
17
- // i need to extract the iamge name from the url
18
18
  var match = o.image.match(/([^/]+)_(\d+)\.png$/);
19
19
  if (match) {
20
20
  o.stimulus = match[0];
@@ -38,7 +38,6 @@ var gonogo_extract_trials = function (obj) {
38
38
  o.should_go = o.stimulus == "rocket_trans_1.png";
39
39
  break;
40
40
  case 4:
41
- // should go in all cases where the goal is NOT the rocket
42
41
  o.should_go = !(o.stimulus == "rocket_trans_1.png");
43
42
  break;
44
43
  default:
@@ -50,22 +49,70 @@ var gonogo_extract_trials = function (obj) {
50
49
  return trials;
51
50
  };
52
51
  exports.gonogo_extract_trials = gonogo_extract_trials;
52
+ // TODO this
53
+ var calculate_performance_score = function (avg_rt, avg_acc) {
54
+ var performance = avg_rt / (Math.pow(avg_acc, 5) + 0.001);
55
+ performance = Math.min(Math.max(performance, BEST_SCORE), WORST_SCORE);
56
+ var performance_score = (1 - ((performance - BEST_SCORE) / (WORST_SCORE - BEST_SCORE))) * 100;
57
+ return performance_score;
58
+ };
53
59
  var gonogo_results = function (data) {
54
60
  // throw error if obj is empty
55
61
  if (data.length === 0) {
56
62
  throw new Error("No trials found");
57
63
  }
58
- var results = {
59
- n: data.length,
60
- avg_rt: data.reduce(function (a, b) { return a + b.rt; }, 0) / data.length,
61
- avg_acc: data.reduce(function (a, b) { return a + b.correct; }, 0) / data.length,
62
- performance: NaN
64
+ var correct_trials = data.filter(function (o) { return o.correct === true; });
65
+ var incorrect_trials = data.filter(function (o) { return o.correct === false; });
66
+ var missing_trials = []; // technically not possible in GNG, as no response is just incorrect
67
+ var go_trials = data.filter(function (o) { return o.should_go === true; });
68
+ var nogo_trials = data.filter(function (o) { return o.should_go === false; });
69
+ var total_rt = data.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
70
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
71
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
72
+ var responded_trials = data.filter(function (o) { return o.response !== null; });
73
+ var correct_responded_trials = responded_trials.filter(function (o) { return o.correct === true; });
74
+ var incorrect_responded_trials = responded_trials.filter(function (o) { return o.correct === false; });
75
+ var avg_rt = responded_trials.length > 0 ? total_rt / responded_trials.length : 0;
76
+ var avg_acc = correct_trials.length / data.length;
77
+ // Calculate performance score using the existing formula
78
+ var performance_score = calculate_performance_score(avg_rt, avg_acc);
79
+ var common = {
80
+ n_trials: data.length,
81
+ n_correct_trials: correct_trials.length,
82
+ n_incorrect_trials: incorrect_trials.length,
83
+ avg_rt_total: avg_rt,
84
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_responded_trials.length : 0,
85
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_responded_trials.length : 0,
86
+ performance_score: performance_score
87
+ };
88
+ // Group by block for special results
89
+ var by_block = Object.values(data.reduce(function (acc, trial) {
90
+ var key = trial.block_number || 'unknown';
91
+ if (!acc[key])
92
+ acc[key] = { block: key, trials: [], avg_rt: 0, avg_acc: 0 };
93
+ acc[key].trials.push(trial);
94
+ return acc;
95
+ }, {})).map(function (group) {
96
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
97
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
98
+ return group;
99
+ });
100
+ var special = {
101
+ by_block: by_block,
102
+ go_trials: {
103
+ n: go_trials.length,
104
+ avg_rt: go_trials.length > 0 ? go_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / go_trials.length : 0,
105
+ avg_acc: go_trials.length > 0 ? go_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / go_trials.length : 0,
106
+ },
107
+ nogo_trials: {
108
+ n: nogo_trials.length,
109
+ avg_rt: nogo_trials.length > 0 ? nogo_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / nogo_trials.length : 0,
110
+ avg_acc: nogo_trials.length > 0 ? nogo_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / nogo_trials.length : 0,
111
+ }
112
+ };
113
+ return {
114
+ common: common,
115
+ special: special
63
116
  };
64
- var best_score = 300;
65
- var worst_score = 5000;
66
- var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
67
- performance = Math.min(Math.max(performance, best_score), worst_score);
68
- results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
69
- return results;
70
117
  };
71
118
  exports.gonogo_results = gonogo_results;
@@ -1,9 +1,6 @@
1
- import { NbackResultsStructure } from './nback';
2
- import { SpatialResultsStructure } from './spatial-cognition';
3
- import { GonogoResultsStructure } from './gonogo';
4
- import { EmotionResultsStructure } from './emotions';
1
+ import { NbackResultsStructure, SpatialResultsStructure, GonogoResultsStructure, EmotionResultsStructure, CommonResults } from './common-interfaces';
5
2
  declare const NbackResults: (obj: any[]) => NbackResultsStructure;
6
3
  declare const SpatialCognitionResults: (obj: any[]) => SpatialResultsStructure;
7
4
  declare const GonogoResults: (obj: any[]) => GonogoResultsStructure;
8
5
  declare const EmotionResults: (obj: any[]) => EmotionResultsStructure;
9
- export { NbackResults, SpatialCognitionResults, EmotionResults, GonogoResults };
6
+ export { NbackResults, SpatialCognitionResults, EmotionResults, GonogoResults, NbackResultsStructure, SpatialResultsStructure, GonogoResultsStructure, EmotionResultsStructure, CommonResults };
@@ -1,15 +1,5 @@
1
+ import { NbackResultsStructure } from './common-interfaces';
1
2
  declare const nback_calculate_results: (obj: any[]) => NbackResultsStructure;
2
3
  declare const nback_extract_trials: (obj: any[]) => any[];
3
- interface NbackTrialResultsStructure {
4
- n: number;
5
- avg_rt: number;
6
- avg_acc: number;
7
- }
8
- interface NbackResultsStructure {
9
- total_trials: NbackTrialResultsStructure;
10
- target_trials: NbackTrialResultsStructure;
11
- non_target_trials: NbackTrialResultsStructure;
12
- performance: number;
13
- }
14
4
  declare const nback_results: (trials: any[]) => NbackResultsStructure;
15
5
  export { nback_extract_trials, nback_results, nback_calculate_results, NbackResultsStructure };