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/dist/cjs/nback.js CHANGED
@@ -15,25 +15,39 @@ exports.nback_extract_trials = nback_extract_trials;
15
15
  var nback_results = function (trials) {
16
16
  var target_trials = trials.filter(function (o) { return o.is_target; });
17
17
  var non_target_trials = trials.filter(function (o) { return !o.is_target; });
18
- var results = {
19
- total_trials: {
20
- n: trials.length,
21
- avg_rt: trials.reduce(function (a, b) { return a + b.rt; }, 0) / trials.length,
22
- avg_acc: trials.reduce(function (a, b) { return a + b.correct; }, 0) / trials.length,
23
- },
18
+ var correct_trials = trials.filter(function (o) { return o.correct === true; });
19
+ var incorrect_trials = trials.filter(function (o) { return o.correct === false; });
20
+ var total_rt = trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
21
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
22
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
23
+ var responded_trials = trials.filter(function (o) { return o.response !== null; });
24
+ var correct_responded_trials = responded_trials.filter(function (o) { return o.correct === true; });
25
+ var incorrect_responded_trials = responded_trials.filter(function (o) { return o.correct === false; });
26
+ var common = {
27
+ n_trials: trials.length,
28
+ n_correct_trials: correct_trials.length,
29
+ n_incorrect_trials: incorrect_trials.length,
30
+ avg_rt_total: trials.length > 0 ? total_rt / responded_trials.length : 0,
31
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_responded_trials.length : 0,
32
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_responded_trials.length : 0,
33
+ performance_score: trials.length > 0 ? correct_trials.length * 100 / trials.length : 0
34
+ };
35
+ var special = {
24
36
  target_trials: {
25
37
  n: target_trials.length,
26
- avg_rt: target_trials.reduce(function (a, b) { return a + b.rt; }, 0) / target_trials.length,
27
- avg_acc: target_trials.reduce(function (a, b) { return a + b.correct; }, 0) / target_trials.length,
38
+ avg_rt: target_trials.length > 0 ? target_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / target_trials.length : 0,
39
+ avg_acc: target_trials.length > 0 ? target_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) * 100 / target_trials.length : 0,
28
40
  },
29
41
  non_target_trials: {
30
42
  n: non_target_trials.length,
31
- avg_rt: non_target_trials.reduce(function (a, b) { return a + b.rt; }, 0) / non_target_trials.length,
32
- avg_acc: non_target_trials.reduce(function (a, b) { return a + b.correct; }, 0) / non_target_trials.length,
33
- },
34
- performance: NaN
43
+ avg_rt: non_target_trials.length > 0 ? non_target_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / non_target_trials.length : 0,
44
+ avg_acc: non_target_trials.length > 0 ? non_target_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) * 100 / non_target_trials.length : 0,
45
+ }
46
+ };
47
+ var results = {
48
+ common: common,
49
+ special: special
35
50
  };
36
- results.performance = results.total_trials.avg_acc;
37
51
  console.log(results);
38
52
  return results;
39
53
  };
@@ -1,9 +1,4 @@
1
- interface SpatialResultsStructure {
2
- n: number;
3
- avg_rt: number;
4
- avg_acc: number;
5
- performance: number;
6
- }
1
+ import { SpatialResultsStructure } from './common-interfaces';
7
2
  declare const spatial_calculate_results: (obj: any[]) => SpatialResultsStructure;
8
3
  declare const spatial_extract_trials: (obj: any[]) => any[];
9
4
  declare const spatial_results: (obj: any[]) => SpatialResultsStructure;
@@ -1,11 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.spatial_calculate_results = exports.spatial_results = exports.spatial_extract_trials = exports.spatial_extract_image_info = void 0;
4
+ var BEST_SCORE = 1000;
5
+ var WORST_SCORE = 10000;
4
6
  var spatial_calculate_results = function (obj) {
5
7
  var trials = spatial_extract_trials(obj);
6
8
  return spatial_results(trials);
7
9
  };
8
10
  exports.spatial_calculate_results = spatial_calculate_results;
11
+ var calculate_performance_score = function (avg_rt, avg_acc) {
12
+ var performance = avg_rt / (avg_acc + 0.001);
13
+ performance = Math.min(Math.max(performance, BEST_SCORE), WORST_SCORE);
14
+ var performance_score = (1 - ((performance - BEST_SCORE) / (WORST_SCORE - BEST_SCORE))) * 100;
15
+ return performance_score;
16
+ };
9
17
  var spatial_extract_trials = function (obj) {
10
18
  var trials = obj.filter(function (o) { return 'stimulus' in o &&
11
19
  o.stimulus.startsWith("<img src="); });
@@ -14,21 +22,68 @@ var spatial_extract_trials = function (obj) {
14
22
  };
15
23
  exports.spatial_extract_trials = spatial_extract_trials;
16
24
  var spatial_results = function (obj) {
17
- var results = {
18
- n: obj.length,
19
- avg_rt: obj.reduce(function (a, b) { return a + b.rt; }, 0) / obj.length,
20
- avg_acc: obj.reduce(function (a, b) { return a + b.correct; }, 0) / obj.length,
21
- performance: NaN
25
+ var correct_trials = obj.filter(function (o) { return o.correct === 1 || o.correct === true; });
26
+ var incorrect_trials = obj.filter(function (o) { return o.correct === 0 || o.correct === false; });
27
+ var missing_trials = obj.filter(function (o) { return o.response === null || o.response === undefined; });
28
+ var total_rt = obj.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
29
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
30
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
31
+ var missing_rt = missing_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
32
+ var avg_rt = obj.length > 0 ? total_rt / obj.length : 0;
33
+ var avg_acc = obj.length > 0 ? correct_trials.length / obj.length : 0;
34
+ var performance_score = calculate_performance_score(avg_rt, avg_acc);
35
+ var common = {
36
+ n_trials: obj.length,
37
+ n_correct_trials: correct_trials.length,
38
+ n_incorrect_trials: incorrect_trials.length,
39
+ avg_rt_total: avg_rt,
40
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_trials.length : 0,
41
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_trials.length : 0,
42
+ performance_score: performance_score
43
+ };
44
+ // Group by distance, angle, and rotation for special results
45
+ var by_distance = Object.values(obj.reduce(function (acc, trial) {
46
+ var key = trial.distance || 'unknown';
47
+ if (!acc[key])
48
+ acc[key] = { distance: key, trials: [], avg_rt: 0, avg_acc: 0 };
49
+ acc[key].trials.push(trial);
50
+ return acc;
51
+ }, {})).map(function (group) {
52
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
53
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
54
+ return group;
55
+ });
56
+ var by_angle = Object.values(obj.reduce(function (acc, trial) {
57
+ var key = trial.angle || 'unknown';
58
+ if (!acc[key])
59
+ acc[key] = { angle: key, trials: [], avg_rt: 0, avg_acc: 0 };
60
+ acc[key].trials.push(trial);
61
+ return acc;
62
+ }, {})).map(function (group) {
63
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
64
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
65
+ return group;
66
+ });
67
+ var by_rotation = Object.values(obj.reduce(function (acc, trial) {
68
+ var key = trial.rotation || 'unknown';
69
+ if (!acc[key])
70
+ acc[key] = { rotation: key, trials: [], avg_rt: 0, avg_acc: 0 };
71
+ acc[key].trials.push(trial);
72
+ return acc;
73
+ }, {})).map(function (group) {
74
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
75
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
76
+ return group;
77
+ });
78
+ var special = {
79
+ by_distance: by_distance,
80
+ by_angle: by_angle,
81
+ by_rotation: by_rotation
82
+ };
83
+ return {
84
+ common: common,
85
+ special: special
22
86
  };
23
- var best_score = 1000;
24
- var worst_score = 10000;
25
- // results.avg_acc to the power of 5
26
- //let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
27
- var performance = results.avg_rt / (results.avg_acc + 0.001);
28
- performance = Math.min(Math.max(performance, best_score), worst_score);
29
- // convert to 0-100 where 100 is the best (200)
30
- results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
31
- return results;
32
87
  };
33
88
  exports.spatial_results = spatial_results;
34
89
  var spatial_extract_image_info = function (obj) {
@@ -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 @@
1
+ export {};
@@ -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,31 +1,12 @@
1
+ var EMOTION_MAP = ["neutral", "sad", "happy", "surprised", "angry"];
1
2
  var emotion_calculate_results = function (obj) {
2
3
  var trials = emotion_extract_trials(obj);
3
- // throw if trials is empty
4
4
  if (trials.length === 0) {
5
5
  throw new Error("No trials found");
6
6
  }
7
7
  return emotion_results(trials);
8
8
  };
9
- var emotion_results = function (obj) {
10
- // throw error if obj is empty
11
- if (obj.length === 0) {
12
- throw new Error("No trials found");
13
- }
14
- var results = {
15
- n: obj.length,
16
- avg_rt: obj.reduce(function (a, b) { return a + b.rt; }, 0) / obj.length,
17
- avg_acc: obj.reduce(function (a, b) { return a + b.correct; }, 0) / obj.length,
18
- performance: NaN
19
- };
20
- var best_score = 1000;
21
- var worst_score = 10000;
22
- var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
23
- performance = Math.min(Math.max(performance, best_score), worst_score);
24
- results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
25
- return results;
26
- };
27
9
  var emotion_extract_trials = function (obj) {
28
- var emotionMap = ["neutral", "sad", "happy", "surprised", "angry"];
29
10
  // filter trials where response and rt are defined and not null
30
11
  var trials = obj.filter(function (o) { return 'response' in o && 'rt' in o && 'emotion' in o; });
31
12
  trials = trials.filter(function (o) { return o.response !== null && o.rt !== null; });
@@ -40,10 +21,63 @@ var emotion_extract_trials = function (obj) {
40
21
  }
41
22
  });
42
23
  trials.forEach(function (o) {
43
- o.emotion_response = emotionMap[o.response] || "unknown";
24
+ o.emotion_response = EMOTION_MAP[o.response] || "unknown";
44
25
  o.correct = o.emotion === o.emotion_response;
45
26
  // in the older ones there were 15 trials per rotation
46
27
  });
47
28
  return trials;
48
29
  };
30
+ var emotion_results = function (obj) {
31
+ if (obj.length === 0) {
32
+ throw new Error("No trials found");
33
+ }
34
+ var correct_trials = obj.filter(function (o) { return o.correct === true; });
35
+ var incorrect_trials = obj.filter(function (o) { return o.correct === false; });
36
+ var total_rt = obj.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
37
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
38
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
39
+ var avg_rt = total_rt / obj.length;
40
+ var avg_acc = correct_trials.length / obj.length;
41
+ // Calculate performance score using the existing formula
42
+ var best_score = 1000;
43
+ var worst_score = 10000;
44
+ var performance = avg_rt / (Math.pow(avg_acc, 5) + 0.001);
45
+ performance = Math.min(Math.max(performance, best_score), worst_score);
46
+ var performance_score = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
47
+ var common = {
48
+ n_trials: obj.length,
49
+ n_correct_trials: correct_trials.length,
50
+ n_incorrect_trials: incorrect_trials.length,
51
+ avg_rt_total: avg_rt,
52
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_trials.length : 0,
53
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_trials.length : 0,
54
+ performance_score: performance_score
55
+ };
56
+ // Group by emotion for special results
57
+ var by_emotion = EMOTION_MAP.map(function (emotion) {
58
+ var emotion_trials = obj.filter(function (o) { return o.emotion === emotion; });
59
+ return {
60
+ emotion: emotion,
61
+ n: emotion_trials.length,
62
+ avg_rt: emotion_trials.length > 0 ? emotion_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / emotion_trials.length : 0,
63
+ avg_acc: emotion_trials.length > 0 ? emotion_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / emotion_trials.length : 0,
64
+ };
65
+ });
66
+ // Create confusion matrix
67
+ var confusion_matrix = EMOTION_MAP.reduce(function (matrix, actual) {
68
+ matrix[actual] = EMOTION_MAP.reduce(function (row, predicted) {
69
+ row[predicted] = obj.filter(function (o) { return o.emotion === actual && o.emotion_response === predicted; }).length;
70
+ return row;
71
+ }, {});
72
+ return matrix;
73
+ }, {});
74
+ var special = {
75
+ by_emotion: by_emotion,
76
+ confusion_matrix: confusion_matrix
77
+ };
78
+ return {
79
+ common: common,
80
+ special: special
81
+ };
82
+ };
49
83
  export { emotion_calculate_results, emotion_extract_trials, 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,3 +1,5 @@
1
+ var BEST_SCORE = 300;
2
+ var WORST_SCORE = 5000;
1
3
  var gonogo_calculate_results = function (data) {
2
4
  var trials = gonogo_extract_trials(data);
3
5
  var results = gonogo_results(trials);
@@ -8,9 +10,7 @@ var gonogo_extract_trials = function (obj) {
8
10
  var trials = obj.filter(function (o) { return 'image' in o && o.image !== undefined; });
9
11
  trials.forEach(function (o) {
10
12
  // image is in format <stimulus>_trans_<number>.png
11
- // extract the stimulus and number
12
13
  // "image": "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/astronaut_trans_1.png",
13
- // i need to extract the iamge name from the url
14
14
  var match = o.image.match(/([^/]+)_(\d+)\.png$/);
15
15
  if (match) {
16
16
  o.stimulus = match[0];
@@ -34,7 +34,6 @@ var gonogo_extract_trials = function (obj) {
34
34
  o.should_go = o.stimulus == "rocket_trans_1.png";
35
35
  break;
36
36
  case 4:
37
- // should go in all cases where the goal is NOT the rocket
38
37
  o.should_go = !(o.stimulus == "rocket_trans_1.png");
39
38
  break;
40
39
  default:
@@ -45,22 +44,70 @@ var gonogo_extract_trials = function (obj) {
45
44
  });
46
45
  return trials;
47
46
  };
47
+ // TODO this
48
+ var calculate_performance_score = function (avg_rt, avg_acc) {
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
+ return performance_score;
53
+ };
48
54
  var gonogo_results = function (data) {
49
55
  // throw error if obj is empty
50
56
  if (data.length === 0) {
51
57
  throw new Error("No trials found");
52
58
  }
53
- var results = {
54
- n: data.length,
55
- avg_rt: data.reduce(function (a, b) { return a + b.rt; }, 0) / data.length,
56
- avg_acc: data.reduce(function (a, b) { return a + b.correct; }, 0) / data.length,
57
- performance: NaN
59
+ var correct_trials = data.filter(function (o) { return o.correct === true; });
60
+ var incorrect_trials = data.filter(function (o) { return o.correct === false; });
61
+ var missing_trials = []; // technically not possible in GNG, as no response is just incorrect
62
+ var go_trials = data.filter(function (o) { return o.should_go === true; });
63
+ var nogo_trials = data.filter(function (o) { return o.should_go === false; });
64
+ var total_rt = data.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
65
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
66
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
67
+ var responded_trials = data.filter(function (o) { return o.response !== null; });
68
+ var correct_responded_trials = responded_trials.filter(function (o) { return o.correct === true; });
69
+ var incorrect_responded_trials = responded_trials.filter(function (o) { return o.correct === false; });
70
+ var avg_rt = responded_trials.length > 0 ? total_rt / responded_trials.length : 0;
71
+ var avg_acc = correct_trials.length / data.length;
72
+ // Calculate performance score using the existing formula
73
+ var performance_score = calculate_performance_score(avg_rt, avg_acc);
74
+ var common = {
75
+ n_trials: data.length,
76
+ n_correct_trials: correct_trials.length,
77
+ n_incorrect_trials: incorrect_trials.length,
78
+ avg_rt_total: avg_rt,
79
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_responded_trials.length : 0,
80
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_responded_trials.length : 0,
81
+ performance_score: performance_score
82
+ };
83
+ // Group by block for special results
84
+ var by_block = Object.values(data.reduce(function (acc, trial) {
85
+ var key = trial.block_number || 'unknown';
86
+ if (!acc[key])
87
+ acc[key] = { block: key, trials: [], avg_rt: 0, avg_acc: 0 };
88
+ acc[key].trials.push(trial);
89
+ return acc;
90
+ }, {})).map(function (group) {
91
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
92
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
93
+ return group;
94
+ });
95
+ var special = {
96
+ by_block: by_block,
97
+ go_trials: {
98
+ n: go_trials.length,
99
+ avg_rt: go_trials.length > 0 ? go_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / go_trials.length : 0,
100
+ avg_acc: go_trials.length > 0 ? go_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / go_trials.length : 0,
101
+ },
102
+ nogo_trials: {
103
+ n: nogo_trials.length,
104
+ avg_rt: nogo_trials.length > 0 ? nogo_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / nogo_trials.length : 0,
105
+ avg_acc: nogo_trials.length > 0 ? nogo_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / nogo_trials.length : 0,
106
+ }
107
+ };
108
+ return {
109
+ common: common,
110
+ special: special
58
111
  };
59
- var best_score = 300;
60
- var worst_score = 5000;
61
- var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
62
- performance = Math.min(Math.max(performance, best_score), worst_score);
63
- results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
64
- return results;
65
112
  };
66
113
  export { gonogo_calculate_results, gonogo_extract_trials, 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 };
package/dist/esm/nback.js CHANGED
@@ -10,25 +10,39 @@ var nback_extract_trials = function (obj) {
10
10
  var nback_results = function (trials) {
11
11
  var target_trials = trials.filter(function (o) { return o.is_target; });
12
12
  var non_target_trials = trials.filter(function (o) { return !o.is_target; });
13
- var results = {
14
- total_trials: {
15
- n: trials.length,
16
- avg_rt: trials.reduce(function (a, b) { return a + b.rt; }, 0) / trials.length,
17
- avg_acc: trials.reduce(function (a, b) { return a + b.correct; }, 0) / trials.length,
18
- },
13
+ var correct_trials = trials.filter(function (o) { return o.correct === true; });
14
+ var incorrect_trials = trials.filter(function (o) { return o.correct === false; });
15
+ var total_rt = trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
16
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
17
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
18
+ var responded_trials = trials.filter(function (o) { return o.response !== null; });
19
+ var correct_responded_trials = responded_trials.filter(function (o) { return o.correct === true; });
20
+ var incorrect_responded_trials = responded_trials.filter(function (o) { return o.correct === false; });
21
+ var common = {
22
+ n_trials: trials.length,
23
+ n_correct_trials: correct_trials.length,
24
+ n_incorrect_trials: incorrect_trials.length,
25
+ avg_rt_total: trials.length > 0 ? total_rt / responded_trials.length : 0,
26
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_responded_trials.length : 0,
27
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_responded_trials.length : 0,
28
+ performance_score: trials.length > 0 ? correct_trials.length * 100 / trials.length : 0
29
+ };
30
+ var special = {
19
31
  target_trials: {
20
32
  n: target_trials.length,
21
- avg_rt: target_trials.reduce(function (a, b) { return a + b.rt; }, 0) / target_trials.length,
22
- avg_acc: target_trials.reduce(function (a, b) { return a + b.correct; }, 0) / target_trials.length,
33
+ avg_rt: target_trials.length > 0 ? target_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / target_trials.length : 0,
34
+ avg_acc: target_trials.length > 0 ? target_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) * 100 / target_trials.length : 0,
23
35
  },
24
36
  non_target_trials: {
25
37
  n: non_target_trials.length,
26
- avg_rt: non_target_trials.reduce(function (a, b) { return a + b.rt; }, 0) / non_target_trials.length,
27
- avg_acc: non_target_trials.reduce(function (a, b) { return a + b.correct; }, 0) / non_target_trials.length,
28
- },
29
- performance: NaN
38
+ avg_rt: non_target_trials.length > 0 ? non_target_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / non_target_trials.length : 0,
39
+ avg_acc: non_target_trials.length > 0 ? non_target_trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) * 100 / non_target_trials.length : 0,
40
+ }
41
+ };
42
+ var results = {
43
+ common: common,
44
+ special: special
30
45
  };
31
- results.performance = results.total_trials.avg_acc;
32
46
  console.log(results);
33
47
  return results;
34
48
  };
@@ -1,9 +1,4 @@
1
- interface SpatialResultsStructure {
2
- n: number;
3
- avg_rt: number;
4
- avg_acc: number;
5
- performance: number;
6
- }
1
+ import { SpatialResultsStructure } from './common-interfaces';
7
2
  declare const spatial_calculate_results: (obj: any[]) => SpatialResultsStructure;
8
3
  declare const spatial_extract_trials: (obj: any[]) => any[];
9
4
  declare const spatial_results: (obj: any[]) => SpatialResultsStructure;
@@ -1,7 +1,15 @@
1
+ var BEST_SCORE = 1000;
2
+ var WORST_SCORE = 10000;
1
3
  var spatial_calculate_results = function (obj) {
2
4
  var trials = spatial_extract_trials(obj);
3
5
  return spatial_results(trials);
4
6
  };
7
+ var calculate_performance_score = function (avg_rt, avg_acc) {
8
+ var performance = avg_rt / (avg_acc + 0.001);
9
+ performance = Math.min(Math.max(performance, BEST_SCORE), WORST_SCORE);
10
+ var performance_score = (1 - ((performance - BEST_SCORE) / (WORST_SCORE - BEST_SCORE))) * 100;
11
+ return performance_score;
12
+ };
5
13
  var spatial_extract_trials = function (obj) {
6
14
  var trials = obj.filter(function (o) { return 'stimulus' in o &&
7
15
  o.stimulus.startsWith("<img src="); });
@@ -9,21 +17,68 @@ var spatial_extract_trials = function (obj) {
9
17
  return trials;
10
18
  };
11
19
  var spatial_results = function (obj) {
12
- var results = {
13
- n: obj.length,
14
- avg_rt: obj.reduce(function (a, b) { return a + b.rt; }, 0) / obj.length,
15
- avg_acc: obj.reduce(function (a, b) { return a + b.correct; }, 0) / obj.length,
16
- performance: NaN
20
+ var correct_trials = obj.filter(function (o) { return o.correct === 1 || o.correct === true; });
21
+ var incorrect_trials = obj.filter(function (o) { return o.correct === 0 || o.correct === false; });
22
+ var missing_trials = obj.filter(function (o) { return o.response === null || o.response === undefined; });
23
+ var total_rt = obj.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
24
+ var correct_rt = correct_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
25
+ var incorrect_rt = incorrect_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
26
+ var missing_rt = missing_trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0);
27
+ var avg_rt = obj.length > 0 ? total_rt / obj.length : 0;
28
+ var avg_acc = obj.length > 0 ? correct_trials.length / obj.length : 0;
29
+ var performance_score = calculate_performance_score(avg_rt, avg_acc);
30
+ var common = {
31
+ n_trials: obj.length,
32
+ n_correct_trials: correct_trials.length,
33
+ n_incorrect_trials: incorrect_trials.length,
34
+ avg_rt_total: avg_rt,
35
+ avg_rt_correct: correct_trials.length > 0 ? correct_rt / correct_trials.length : 0,
36
+ avg_rt_incorrect: incorrect_trials.length > 0 ? incorrect_rt / incorrect_trials.length : 0,
37
+ performance_score: performance_score
38
+ };
39
+ // Group by distance, angle, and rotation for special results
40
+ var by_distance = Object.values(obj.reduce(function (acc, trial) {
41
+ var key = trial.distance || 'unknown';
42
+ if (!acc[key])
43
+ acc[key] = { distance: key, trials: [], avg_rt: 0, avg_acc: 0 };
44
+ acc[key].trials.push(trial);
45
+ return acc;
46
+ }, {})).map(function (group) {
47
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
48
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
49
+ return group;
50
+ });
51
+ var by_angle = Object.values(obj.reduce(function (acc, trial) {
52
+ var key = trial.angle || 'unknown';
53
+ if (!acc[key])
54
+ acc[key] = { angle: key, trials: [], avg_rt: 0, avg_acc: 0 };
55
+ acc[key].trials.push(trial);
56
+ return acc;
57
+ }, {})).map(function (group) {
58
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
59
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
60
+ return group;
61
+ });
62
+ var by_rotation = Object.values(obj.reduce(function (acc, trial) {
63
+ var key = trial.rotation || 'unknown';
64
+ if (!acc[key])
65
+ acc[key] = { rotation: key, trials: [], avg_rt: 0, avg_acc: 0 };
66
+ acc[key].trials.push(trial);
67
+ return acc;
68
+ }, {})).map(function (group) {
69
+ group.avg_rt = group.trials.reduce(function (a, b) { return a + (b.rt || 0); }, 0) / group.trials.length;
70
+ group.avg_acc = group.trials.reduce(function (a, b) { return a + (b.correct ? 1 : 0); }, 0) / group.trials.length;
71
+ return group;
72
+ });
73
+ var special = {
74
+ by_distance: by_distance,
75
+ by_angle: by_angle,
76
+ by_rotation: by_rotation
77
+ };
78
+ return {
79
+ common: common,
80
+ special: special
17
81
  };
18
- var best_score = 1000;
19
- var worst_score = 10000;
20
- // results.avg_acc to the power of 5
21
- //let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
22
- var performance = results.avg_rt / (results.avg_acc + 0.001);
23
- performance = Math.min(Math.max(performance, best_score), worst_score);
24
- // convert to 0-100 where 100 is the best (200)
25
- results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
26
- return results;
27
82
  };
28
83
  var spatial_extract_image_info = function (obj) {
29
84
  // from the following field, extract the final image name (map_left_1_90.png), and rotation from the class attribute (rotate_0)