From 33bee7eb1ea22e83a5cc75eadd1fa4edfd587f54 Mon Sep 17 00:00:00 2001 From: Nick Hellemans Date: Thu, 2 Jan 2025 19:59:32 +0100 Subject: [PATCH] feat(calcs): gad --- {todo => src/scores}/GAD_2/README.md | 0 .../__testdata__/gad_2_test_responses.ts | 0 .../scores}/GAD_2/definition/gad_2_inputs.ts | 25 ++- .../GAD_2/definition/gad_2_interpretation.ts | 0 src/scores/GAD_2/definition/gad_2_output.ts | 13 ++ .../scores}/GAD_2/definition/index.ts | 0 src/scores/GAD_2/gad_2.test.ts | 114 ++++++++++++++ src/scores/GAD_2/gad_2.ts | 22 +++ {todo => src/scores}/GAD_7/README.md | 0 .../__testdata__/gad_7_test_responses.ts | 0 .../scores}/GAD_7/definition/gad_7_inputs.ts | 70 ++++----- .../GAD_7/definition/gad_7_interpretation.ts | 0 src/scores/GAD_7/definition/gad_7_output.ts | 13 ++ .../scores}/GAD_7/definition/index.ts | 0 src/scores/GAD_7/gad_7.test.ts | 118 ++++++++++++++ src/scores/GAD_7/gad_7.ts | 18 +++ src/scores/library.ts | 8 +- todo/GAD_2/definition/gad_2_output.ts | 14 -- todo/GAD_2/gad_2.test.ts | 139 ----------------- todo/GAD_2/gad_2.ts | 66 -------- todo/GAD_7/definition/gad_7_output.ts | 14 -- todo/GAD_7/gad_7.test.ts | 147 ------------------ todo/GAD_7/gad_7.ts | 62 -------- 23 files changed, 346 insertions(+), 497 deletions(-) rename {todo => src/scores}/GAD_2/README.md (100%) rename {todo => src/scores}/GAD_2/__testdata__/gad_2_test_responses.ts (100%) rename {todo => src/scores}/GAD_2/definition/gad_2_inputs.ts (79%) rename {todo => src/scores}/GAD_2/definition/gad_2_interpretation.ts (100%) create mode 100644 src/scores/GAD_2/definition/gad_2_output.ts rename {todo => src/scores}/GAD_2/definition/index.ts (100%) create mode 100644 src/scores/GAD_2/gad_2.test.ts create mode 100644 src/scores/GAD_2/gad_2.ts rename {todo => src/scores}/GAD_7/README.md (100%) rename {todo => src/scores}/GAD_7/__testdata__/gad_7_test_responses.ts (100%) rename {todo => src/scores}/GAD_7/definition/gad_7_inputs.ts (81%) rename {todo => src/scores}/GAD_7/definition/gad_7_interpretation.ts (100%) create mode 100644 src/scores/GAD_7/definition/gad_7_output.ts rename {todo => src/scores}/GAD_7/definition/index.ts (100%) create mode 100644 src/scores/GAD_7/gad_7.test.ts create mode 100644 src/scores/GAD_7/gad_7.ts delete mode 100644 todo/GAD_2/definition/gad_2_output.ts delete mode 100644 todo/GAD_2/gad_2.test.ts delete mode 100644 todo/GAD_2/gad_2.ts delete mode 100644 todo/GAD_7/definition/gad_7_output.ts delete mode 100644 todo/GAD_7/gad_7.test.ts delete mode 100644 todo/GAD_7/gad_7.ts diff --git a/todo/GAD_2/README.md b/src/scores/GAD_2/README.md similarity index 100% rename from todo/GAD_2/README.md rename to src/scores/GAD_2/README.md diff --git a/todo/GAD_2/__testdata__/gad_2_test_responses.ts b/src/scores/GAD_2/__testdata__/gad_2_test_responses.ts similarity index 100% rename from todo/GAD_2/__testdata__/gad_2_test_responses.ts rename to src/scores/GAD_2/__testdata__/gad_2_test_responses.ts diff --git a/todo/GAD_2/definition/gad_2_inputs.ts b/src/scores/GAD_2/definition/gad_2_inputs.ts similarity index 79% rename from todo/GAD_2/definition/gad_2_inputs.ts rename to src/scores/GAD_2/definition/gad_2_inputs.ts index 9961dec..f171e67 100644 --- a/todo/GAD_2/definition/gad_2_inputs.ts +++ b/src/scores/GAD_2/definition/gad_2_inputs.ts @@ -1,15 +1,15 @@ -import type { InputType } from '../../../src/types/calculations.types' +import { z } from 'zod' +import { ScoreInputSchemaType } from '../../../types' -export const GAD2_INPUTS: Array = [ - { - input_id: 'GAD2_Q01', +export const GAD2_INPUTS = { + GAD2_Q01: { label: { en: 'Over the last two weeks, how often have you been bothered by feeling nervous, anxious, or on edge?', nl: 'Hoe vaak hebt u in de afgelopen 2 weken last gehad van uzelf zenuwachtig, angstig of gespannen te voelen?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -32,15 +32,14 @@ export const GAD2_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD2_Q02', + GAD2_Q02: { label: { en: 'Over the last two weeks, how often have you been bothered by not being able to stop or control worrying?', nl: 'Hoe vaak hebt u in de afgelopen 2 weken last gehad van niet in staat te zijn om te stoppen met piekeren of om controle te krijgen over het piekeren?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -63,4 +62,4 @@ export const GAD2_INPUTS: Array = [ ], }, }, -] +} satisfies ScoreInputSchemaType diff --git a/todo/GAD_2/definition/gad_2_interpretation.ts b/src/scores/GAD_2/definition/gad_2_interpretation.ts similarity index 100% rename from todo/GAD_2/definition/gad_2_interpretation.ts rename to src/scores/GAD_2/definition/gad_2_interpretation.ts diff --git a/src/scores/GAD_2/definition/gad_2_output.ts b/src/scores/GAD_2/definition/gad_2_output.ts new file mode 100644 index 0000000..775b607 --- /dev/null +++ b/src/scores/GAD_2/definition/gad_2_output.ts @@ -0,0 +1,13 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const GAD2_OUTPUT = { + GAD2_SCORE: { + label: { en: 'GAD-2 Score' }, + type: z.number(), + }, + GAD2_INTERPRETATION: { + label: { en: 'GAD-2 Interpretation' }, + type: z.string(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/GAD_2/definition/index.ts b/src/scores/GAD_2/definition/index.ts similarity index 100% rename from todo/GAD_2/definition/index.ts rename to src/scores/GAD_2/definition/index.ts diff --git a/src/scores/GAD_2/gad_2.test.ts b/src/scores/GAD_2/gad_2.test.ts new file mode 100644 index 0000000..4888690 --- /dev/null +++ b/src/scores/GAD_2/gad_2.test.ts @@ -0,0 +1,114 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + best_response, + random_response, + worst_response, +} from './__testdata__/gad_2_test_responses' +import { gad_2 } from './gad_2' + +const BEST_SCORE = 0 +const WORST_SCORE = 6 + +const gad_2_calculation = new Score(gad_2) + +describe('gad_2', function () { + it('gad_2 calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('gad_2') + }) + + describe('basic assumptions', function () { + const outcome = gad_2_calculation.calculate({ payload: best_response }) + + it('should return 2 calculation results', function () { + expect(Object.keys(outcome).length).toEqual(2) + }) + + it('should have the expected calculation result ids', function () { + const EXPECTED_CALCULATION_ID = ['GAD2_SCORE', 'GAD2_INTERPRETATION'] + + const configured_calculation_id = Object.keys(outcome) + + expect(configured_calculation_id).toEqual(EXPECTED_CALCULATION_ID) + }) + }) + + describe('validation', function () { + describe('the score includes the correct input fields', function () { + it('should have all the expected input ids configured', function () { + const EXPECTED_INPUT_IDS = ['GAD2_Q01', 'GAD2_Q02'] + + const configured_input_ids = Object.keys( + gad_2_calculation.inputSchemaAsObject.shape, + ) + + expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) + }) + }) + + describe('when an answer is not not one of the allowed answers', function () { + it('should throw an InvalidInputsError', function () { + expect(() => + gad_2_calculation.calculate({ + payload: { + GAD2_Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with an empty response', function () { + it('should throw a ZodError', function () { + expect(() => gad_2_calculation.calculate({ payload: {} })).toThrow( + ZodError, + ) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with the best response', function () { + const outcome = gad_2_calculation.calculate({ payload: best_response }) + + it('should return the best score', function () { + expect(outcome.GAD2_SCORE).toEqual(BEST_SCORE) + }) + + it('should return the "No anxiety" interpretation', function () { + expect(outcome.GAD2_INTERPRETATION).toEqual('No anxiety') + }) + }) + + describe('when called with the worst response', function () { + const outcome = gad_2_calculation.calculate({ + payload: worst_response, + }) + + it('should return the worst score', function () { + expect(outcome.GAD2_SCORE).toEqual(WORST_SCORE) + }) + + it('should return the "severe anxiety" interpretation', function () { + expect(outcome.GAD2_INTERPRETATION).toEqual('Severe anxiety') + }) + }) + + describe('when called with a random response', function () { + const outcome = gad_2_calculation.calculate({ + payload: random_response, + }) + + it('should return the expected score', function () { + const EXPECTED_SCORE = 3 + + expect(outcome.GAD2_SCORE).toEqual(EXPECTED_SCORE) + }) + + it('should return the "Mild anxiety" interpretation', function () { + expect(outcome.GAD2_INTERPRETATION).toEqual('Moderate anxiety') + }) + }) + }) +}) diff --git a/src/scores/GAD_2/gad_2.ts b/src/scores/GAD_2/gad_2.ts new file mode 100644 index 0000000..5b03c1d --- /dev/null +++ b/src/scores/GAD_2/gad_2.ts @@ -0,0 +1,22 @@ +import { + GAD2_INPUTS, + GAD2_OUTPUT, + GAD2_INTERPRETATION_TABLE, +} from './definition' +import { ScoreType } from '../../types' +import _ from 'lodash' + +export const gad_2: ScoreType = { + name: 'Generalised Anxiety Disorder Assessment (GAD-2)', + readmeLocation: __dirname, + inputSchema: GAD2_INPUTS, + outputSchema: GAD2_OUTPUT, + calculate: ({ data }) => { + const totalScore = data.GAD2_Q01 + data.GAD2_Q02 + + return { + GAD2_SCORE: totalScore, + GAD2_INTERPRETATION: GAD2_INTERPRETATION_TABLE[totalScore.toString()], + } + }, +} diff --git a/todo/GAD_7/README.md b/src/scores/GAD_7/README.md similarity index 100% rename from todo/GAD_7/README.md rename to src/scores/GAD_7/README.md diff --git a/todo/GAD_7/__testdata__/gad_7_test_responses.ts b/src/scores/GAD_7/__testdata__/gad_7_test_responses.ts similarity index 100% rename from todo/GAD_7/__testdata__/gad_7_test_responses.ts rename to src/scores/GAD_7/__testdata__/gad_7_test_responses.ts diff --git a/todo/GAD_7/definition/gad_7_inputs.ts b/src/scores/GAD_7/definition/gad_7_inputs.ts similarity index 81% rename from todo/GAD_7/definition/gad_7_inputs.ts rename to src/scores/GAD_7/definition/gad_7_inputs.ts index 07112f3..0dbd450 100644 --- a/todo/GAD_7/definition/gad_7_inputs.ts +++ b/src/scores/GAD_7/definition/gad_7_inputs.ts @@ -1,14 +1,14 @@ -import type { InputType } from '../../../src/types/calculations.types' +import { z } from 'zod' +import { ScoreInputSchemaType } from '../../../types' -export const GAD7_INPUTS: Array = [ - { - input_id: 'GAD7_Q01', +export const GAD7_INPUTS = { + GAD7_Q01: { label: { en: 'Over the last two weeks, how often have you been bothered by feeling nervous, anxious, or on edge?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -31,14 +31,13 @@ export const GAD7_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD7_Q02', + GAD7_Q02: { label: { en: 'Over the last two weeks, how often have you been bothered by not being able to stop or control worrying?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -61,14 +60,13 @@ export const GAD7_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD7_Q03', + GAD7_Q03: { label: { en: 'Over the last two weeks, how often have you been bothered by worrying too much about different things?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -91,14 +89,13 @@ export const GAD7_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD7_Q04', + GAD7_Q04: { label: { en: 'Over the last two weeks, how often have you been bothered by trouble relaxing?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -121,14 +118,13 @@ export const GAD7_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD7_Q05', + GAD7_Q05: { label: { en: 'Over the last two weeks, how often have you been bothered by being so restless that it is hard to sit still?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -151,14 +147,13 @@ export const GAD7_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD7_Q06', + GAD7_Q06: { label: { en: 'Over the last two weeks, how often have you been bothered by becoming easily annoyed or irritable?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -181,14 +176,13 @@ export const GAD7_INPUTS: Array = [ ], }, }, - { - input_id: 'GAD7_Q07', + GAD7_Q07: { label: { en: 'Over the last two weeks, how often have you been bothered by feeling afraid, as if something awful might happen?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { label: { en: 'Not at all', nl: 'Helemaal niet' }, value: 0, @@ -211,4 +205,4 @@ export const GAD7_INPUTS: Array = [ ], }, }, -] +} satisfies ScoreInputSchemaType diff --git a/todo/GAD_7/definition/gad_7_interpretation.ts b/src/scores/GAD_7/definition/gad_7_interpretation.ts similarity index 100% rename from todo/GAD_7/definition/gad_7_interpretation.ts rename to src/scores/GAD_7/definition/gad_7_interpretation.ts diff --git a/src/scores/GAD_7/definition/gad_7_output.ts b/src/scores/GAD_7/definition/gad_7_output.ts new file mode 100644 index 0000000..ea60426 --- /dev/null +++ b/src/scores/GAD_7/definition/gad_7_output.ts @@ -0,0 +1,13 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const GAD7_OUTPUT = { + GAD7_SCORE: { + label: { en: 'GAD-7 Score' }, + type: z.number(), + }, + GAD7_INTERPRETATION: { + label: { en: 'GAD-7 Interpretation' }, + type: z.string(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/GAD_7/definition/index.ts b/src/scores/GAD_7/definition/index.ts similarity index 100% rename from todo/GAD_7/definition/index.ts rename to src/scores/GAD_7/definition/index.ts diff --git a/src/scores/GAD_7/gad_7.test.ts b/src/scores/GAD_7/gad_7.test.ts new file mode 100644 index 0000000..f15d387 --- /dev/null +++ b/src/scores/GAD_7/gad_7.test.ts @@ -0,0 +1,118 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + best_response, + random_response, + worst_response, +} from './__testdata__/gad_7_test_responses' +import { gad_7 } from './gad_7' + +const BEST_SCORE = 0 +const WORST_SCORE = 21 + +const gad_7_calculation = new Score(gad_7) + +describe('gad_7', function () { + it('gad_7 calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('gad_7') + }) + + describe('basic assumptions', function () { + const outcome = gad_7_calculation.calculate({ payload: best_response }) + + it('should return 2 calculation results', function () { + expect(Object.keys(outcome)).toHaveLength(2) + }) + + it('should have the expected calculation result ids', function () { + const EXPECTED_CALCULATION_ID = ['GAD7_SCORE', 'GAD7_INTERPRETATION'] + + const configured_calculation_id = Object.keys(outcome) + + expect(configured_calculation_id).toEqual(EXPECTED_CALCULATION_ID) + }) + }) + + describe('validation', function () { + describe('the score includes the correct input fields', function () { + it('should have all the expected input ids configured', function () { + const EXPECTED_INPUT_IDS = [ + 'GAD7_Q01', + 'GAD7_Q02', + 'GAD7_Q03', + 'GAD7_Q04', + 'GAD7_Q05', + 'GAD7_Q06', + 'GAD7_Q07', + ] + + const configured_input_ids = Object.keys( + gad_7_calculation.inputSchemaAsObject.shape, + ) + + expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) + }) + }) + + describe('when an answer is not not one of the allowed answers', function () { + it('should throw an InvalidInputsError', function () { + expect(() => + gad_7_calculation.calculate({ + payload: { + GAD7_Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with an empty response', function () { + it('should throw a ZodError', function () { + expect(() => gad_7_calculation.calculate({ payload: {} })).toThrow( + ZodError, + ) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with the best response', function () { + const outcome = gad_7_calculation.calculate({ payload: best_response }) + + it('should return the best score', function () { + expect(outcome.GAD7_SCORE).toEqual(BEST_SCORE) + }) + + it('should return the "No anxiety" interpretation', function () { + expect(outcome.GAD7_INTERPRETATION).toEqual('No anxiety') + }) + }) + + describe('when called with the worst response', function () { + const outcome = gad_7_calculation.calculate({ payload: worst_response }) + + it('should return the worst score', function () { + expect(outcome.GAD7_SCORE).toEqual(WORST_SCORE) + }) + + it('should return the "severe anxiety" interpretation', function () { + expect(outcome.GAD7_INTERPRETATION).toEqual('Severe anxiety') + }) + }) + + describe('when called with a random response', function () { + const outcome = gad_7_calculation.calculate({ + payload: random_response, + }) + + it('should return the expected score', function () { + expect(outcome.GAD7_SCORE).toEqual(7) + }) + + it('should return the "Mild anxiety" interpretation', function () { + expect(outcome.GAD7_INTERPRETATION).toEqual('Mild anxiety') + }) + }) + }) +}) diff --git a/src/scores/GAD_7/gad_7.ts b/src/scores/GAD_7/gad_7.ts new file mode 100644 index 0000000..847e232 --- /dev/null +++ b/src/scores/GAD_7/gad_7.ts @@ -0,0 +1,18 @@ +import { GAD7_INPUTS, GAD7_OUTPUT, GAD7_INTERPRATION_TABLE } from './definition' +import { ScoreType } from '../../types' +import _ from 'lodash' + +export const gad_7: ScoreType = { + name: 'Generalised Anxiety Disorder Assessment (GAD-7)', + readmeLocation: __dirname, + inputSchema: GAD7_INPUTS, + outputSchema: GAD7_OUTPUT, + calculate: ({ data }) => { + const totalScore = _.sum(Object.values(data)) + + return { + GAD7_SCORE: totalScore, + GAD7_INTERPRETATION: GAD7_INTERPRATION_TABLE[totalScore.toString()], + } + }, +} diff --git a/src/scores/library.ts b/src/scores/library.ts index 9703ca8..1086e98 100644 --- a/src/scores/library.ts +++ b/src/scores/library.ts @@ -49,8 +49,8 @@ import { bmi_metric, bmi_imperial } from './bmi' // } from './forgotten_joint_score_12' // import { pss_4 } from './pss_4/pss_4' // import { stop_bang } from './stop_bang/stop_bang' -// import { gad_2 } from './GAD_2/gad_2' -// import { gad_7 } from './GAD_7/gad_7' +import { gad_2 } from './GAD_2/gad_2' +import { gad_7 } from './GAD_7/gad_7' // import { ghq_12 } from './ghq_12/ghq_12' // import { hads } from './hads/HADS_score' // import { harris_hip_score } from './harris_hip_score/harris_hip_score' @@ -188,8 +188,8 @@ export const ScoreLibrary = createScoreLibrary({ // foot_function_index_5pt, // forgotten_joint_score_hip, // forgotten_joint_score_knee, - // gad_2, - // gad_7, + gad_2, + gad_7, // ghq_12, // hads, // harris_hip_score, diff --git a/todo/GAD_2/definition/gad_2_output.ts b/todo/GAD_2/definition/gad_2_output.ts deleted file mode 100644 index 21bd27b..0000000 --- a/todo/GAD_2/definition/gad_2_output.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const GAD2_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'GAD2_SCORE', - label: { en: 'GAD-2 Score' }, - type: 'number', - }, - { - subresult_id: 'GAD2_INTERPRETATION', - label: { en: 'GAD-2 Interpretation' }, - type: 'string', - }, -] diff --git a/todo/GAD_2/gad_2.test.ts b/todo/GAD_2/gad_2.test.ts deleted file mode 100644 index 47848e8..0000000 --- a/todo/GAD_2/gad_2.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { expect } from 'chai' - -import { InvalidInputsError } from '../../errors' -import { execute_test_calculation } from '../../lib/execute_test_calculation' -import { get_result_ids_from_calculation_output } from '../../lib/get_result_ids_from_calculation_output' -import { view_result } from '../../lib/view_result' -import { view_status } from '../../lib/view_status' -import { MISSING_STATUS } from '../../PARAMETERS' -import { CALCULATIONS } from '../calculation_library' -import { get_input_ids_from_calculation_blueprint } from '../shared_functions' -import { - best_response, - random_response, - worst_response, -} from './__testdata__/gad_2_test_responses' -import { GAD2_INPUTS } from './definition' -import { gad_2 } from './gad_2' - -const BEST_SCORE = 0 -const WORST_SCORE = 6 - -const gad_2_calculation = execute_test_calculation(gad_2) - -describe('gad_2', function () { - it('gad_2 calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('gad_2') - }) - - describe('basic assumptions', function () { - const outcome = gad_2_calculation(best_response) - - it('should return 2 calculation results', function () { - expect(outcome).toHaveLength(2) - }) - - it('should have the expected calculation result ids', function () { - const EXPECTED_CALCULATION_ID = ['GAD2_SCORE', 'GAD2_INTERPRETATION'] - - const configured_calculation_id = - get_result_ids_from_calculation_output(outcome) - - expect(configured_calculation_id).toEqual(EXPECTED_CALCULATION_ID) - }) - }) - - describe('validation', function () { - describe('the score includes the correct input fields', function () { - it('should have all the expected input ids configured', function () { - const EXPECTED_INPUT_IDS = ['GAD2_Q01', 'GAD2_Q02'] - - const configured_input_ids = - get_input_ids_from_calculation_blueprint(GAD2_INPUTS) - - expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) - }) - }) - - describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - gad_2_calculation({ - GAD2_Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with an empty response', function () { - const outcome = gad_2_calculation({}) - - it('should return undefined result and a missing status for the score', function () { - const score = view_result('GAD2_SCORE')(outcome) - const status = view_status('GAD2_SCORE')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - - it('should return undefined result and a missing status for the interpretation', function () { - const score = view_result('GAD2_INTERPRETATION')(outcome) - const status = view_status('GAD2_INTERPRETATION')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with the best response', function () { - const outcome = gad_2_calculation(best_response) - - it('should return the best score', function () { - const score = view_result('GAD2_SCORE')(outcome) - - expect(score).toEqual(BEST_SCORE) - }) - - it('should return the "No anxiety" interpretation', function () { - const score = view_result('GAD2_INTERPRETATION')(outcome) - - expect(score).toEqual('No anxiety') - }) - }) - - describe('when called with the worst response', function () { - const outcome = gad_2_calculation(worst_response) - - it('should return the worst score', function () { - const score = view_result('GAD2_SCORE')(outcome) - - expect(score).toEqual(WORST_SCORE) - }) - - it('should return the "severe anxiety" interpretation', function () { - const score = view_result('GAD2_INTERPRETATION')(outcome) - - expect(score).toEqual('Severe anxiety') - }) - }) - - describe('when called with a random response', function () { - const outcome = gad_2_calculation(random_response) - - it('should return the expected score', function () { - const score = view_result('GAD2_SCORE')(outcome) - const EXPECTED_SCORE = 3 - - expect(score).toEqual(EXPECTED_SCORE) - }) - - it('should return the "Mild anxiety" interpretation', function () { - const score = view_result('GAD2_INTERPRETATION')(outcome) - - expect(score).toEqual('Moderate anxiety') - }) - }) - }) -}) diff --git a/todo/GAD_2/gad_2.ts b/todo/GAD_2/gad_2.ts deleted file mode 100644 index 9dec5f3..0000000 --- a/todo/GAD_2/gad_2.ts +++ /dev/null @@ -1,66 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { rawInputValueLens } from '../../lib/calculation_variants/api/input/lenses' -import { add_raw_values_to_inputs } from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../PARAMETERS' -import { is_numeric } from '../../src/calculation_suite/calculations/shared_functions' -import { - GAD2_INPUTS, - GAD2_INTERPRETATION_TABLE, - GAD2_OUTPUT, -} from './definition' - -const calculate_score = ( - inputs_with_answers: Array, -): WIPCalculationResultType => { - const valid_inputs = R.compose( - R.filter(is_numeric), - R.map(input => R.view(rawInputValueLens, input)), - )(inputs_with_answers) - - if (valid_inputs.length !== GAD2_INPUTS.length) - return [ - { - id: 'GAD2_SCORE', - score: MISSING_MESSAGE, - }, - { - id: 'GAD2_INTERPRETATION', - score: MISSING_MESSAGE, - }, - ] - - const total_score = R.sum(valid_inputs) - - return [ - { - id: 'GAD2_SCORE', - score: total_score, - }, - { - id: 'GAD2_INTERPRETATION', - score: GAD2_INTERPRETATION_TABLE[total_score.toString()], - }, - ] -} - -export const specific_steps_gad_2_calc = [ - calculate_score, - add_raw_values_to_inputs(GAD2_INPUTS), -] - -export const gad_2: CalculationType = create_calculation({ - calculation_name: 'Generalised Anxiety Disorder Assessment (GAD-2)', - readme_location: __dirname, - calculation_steps: specific_steps_gad_2_calc, - calculation_definition: { - input_definition: GAD2_INPUTS, - output_definition: GAD2_OUTPUT, - }, -}) diff --git a/todo/GAD_7/definition/gad_7_output.ts b/todo/GAD_7/definition/gad_7_output.ts deleted file mode 100644 index 574e116..0000000 --- a/todo/GAD_7/definition/gad_7_output.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const GAD7_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'GAD7_SCORE', - label: { en: 'GAD-7 Score' }, - type: 'number', - }, - { - subresult_id: 'GAD7_INTERPRETATION', - label: { en: 'GAD-7 Interpretation' }, - type: 'string', - }, -] diff --git a/todo/GAD_7/gad_7.test.ts b/todo/GAD_7/gad_7.test.ts deleted file mode 100644 index 462d6db..0000000 --- a/todo/GAD_7/gad_7.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { expect } from 'chai' - -import { InvalidInputsError } from '../../errors' -import { execute_test_calculation } from '../../lib/execute_test_calculation' -import { get_result_ids_from_calculation_output } from '../../lib/get_result_ids_from_calculation_output' -import { view_result } from '../../lib/view_result' -import { view_status } from '../../lib/view_status' -import { MISSING_STATUS } from '../../PARAMETERS' -import { CALCULATIONS } from '../calculation_library' -import { get_input_ids_from_calculation_blueprint } from '../shared_functions' -import { - best_response, - random_response, - worst_response, -} from './__testdata__/gad_7_test_responses' -import { GAD7_INPUTS } from './definition' -import { gad_7 } from './gad_7' - -const BEST_SCORE = 0 -const WORST_SCORE = 21 - -const gad_7_calculation = execute_test_calculation(gad_7) - -describe('gad_7', function () { - it('gad_7 calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('gad_7') - }) - - describe('basic assumptions', function () { - const outcome = gad_7_calculation(best_response) - - it('should return 2 calculation results', function () { - expect(outcome).toHaveLength(2) - }) - - it('should have the expected calculation result ids', function () { - const EXPECTED_CALCULATION_ID = ['GAD7_SCORE', 'GAD7_INTERPRETATION'] - - const configured_calculation_id = - get_result_ids_from_calculation_output(outcome) - - expect(configured_calculation_id).toEqual(EXPECTED_CALCULATION_ID) - }) - }) - - describe('validation', function () { - describe('the score includes the correct input fields', function () { - it('should have all the expected input ids configured', function () { - const EXPECTED_INPUT_IDS = [ - 'GAD7_Q01', - 'GAD7_Q02', - 'GAD7_Q03', - 'GAD7_Q04', - 'GAD7_Q05', - 'GAD7_Q06', - 'GAD7_Q07', - ] - - const configured_input_ids = - get_input_ids_from_calculation_blueprint(GAD7_INPUTS) - - expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) - }) - }) - - describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - gad_7_calculation({ - GAD7_Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with an empty response', function () { - const outcome = gad_7_calculation({}) - - it('should return undefined result and a missing status for the score', function () { - const score = view_result('GAD7_SCORE')(outcome) - const status = view_status('GAD7_SCORE')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - - it('should return undefined result and a missing status for the interpretation', function () { - const score = view_result('GAD7_INTERPRETATION')(outcome) - const status = view_status('GAD7_INTERPRETATION')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with the best response', function () { - const outcome = gad_7_calculation(best_response) - - it('should return the best score', function () { - const score = view_result('GAD7_SCORE')(outcome) - - expect(score).toEqual(BEST_SCORE) - }) - - it('should return the "No anxiety" interpretation', function () { - const score = view_result('GAD7_INTERPRETATION')(outcome) - - expect(score).toEqual('No anxiety') - }) - }) - - describe('when called with the worst response', function () { - const outcome = gad_7_calculation(worst_response) - - it('should return the worst score', function () { - const score = view_result('GAD7_SCORE')(outcome) - - expect(score).toEqual(WORST_SCORE) - }) - - it('should return the "severe anxiety" interpretation', function () { - const score = view_result('GAD7_INTERPRETATION')(outcome) - - expect(score).toEqual('Severe anxiety') - }) - }) - - describe('when called with a random response', function () { - const outcome = gad_7_calculation(random_response) - - it('should return the expected score', function () { - const score = view_result('GAD7_SCORE')(outcome) - const EXPECTED_SCORE = 7 - - expect(score).toEqual(EXPECTED_SCORE) - }) - - it('should return the "Mild anxiety" interpretation', function () { - const score = view_result('GAD7_INTERPRETATION')(outcome) - - expect(score).toEqual('Mild anxiety') - }) - }) - }) -}) diff --git a/todo/GAD_7/gad_7.ts b/todo/GAD_7/gad_7.ts deleted file mode 100644 index 7e1e6b8..0000000 --- a/todo/GAD_7/gad_7.ts +++ /dev/null @@ -1,62 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { rawInputValueLens } from '../../lib/calculation_variants/api/input/lenses' -import { add_raw_values_to_inputs } from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../PARAMETERS' -import { is_numeric } from '../../src/calculation_suite/calculations/shared_functions' -import { GAD7_INPUTS, GAD7_INTERPRATION_TABLE, GAD7_OUTPUT } from './definition' - -const calculate_score = ( - inputs_with_answers: Array, -): WIPCalculationResultType => { - const valid_inputs = R.compose( - R.filter(is_numeric), - R.map(input => R.view(rawInputValueLens, input)), - )(inputs_with_answers) - - if (valid_inputs.length !== GAD7_INPUTS.length) - return [ - { - id: 'GAD7_SCORE', - score: MISSING_MESSAGE, - }, - { - id: 'GAD7_INTERPRETATION', - score: MISSING_MESSAGE, - }, - ] - - const total_score = R.sum(valid_inputs) - - return [ - { - id: 'GAD7_SCORE', - score: total_score, - }, - { - id: 'GAD7_INTERPRETATION', - score: GAD7_INTERPRATION_TABLE[total_score.toString()], - }, - ] -} - -export const specific_steps_gad_7_calc = [ - calculate_score, - add_raw_values_to_inputs(GAD7_INPUTS), -] - -export const gad_7: CalculationType = create_calculation({ - calculation_name: 'Generalised Anxiety Disorder Assessment (GAD-7)', - readme_location: __dirname, - calculation_steps: specific_steps_gad_7_calc, - calculation_definition: { - input_definition: GAD7_INPUTS, - output_definition: GAD7_OUTPUT, - }, -})