diff --git a/.pnp.cjs b/.pnp.cjs index f048d1d..c7afb60 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -29,9 +29,8 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@types/cpx", "npm:1.5.5"],\ ["@types/jest", "npm:29.5.14"],\ - ["@types/lodash", "npm:4.17.13"],\ - ["@types/node", "npm:18.19.68"],\ - ["@types/ramda", "npm:0.28.25"],\ + ["@types/lodash", "npm:4.17.14"],\ + ["@types/node", "npm:18.19.69"],\ ["@types/showdown", "npm:2.0.6"],\ ["@typescript-eslint/eslint-plugin", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:8.19.0"],\ ["@typescript-eslint/parser", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:8.19.0"],\ @@ -41,11 +40,9 @@ const RAW_RUNTIME_STATE = ["husky", "npm:9.1.7"],\ ["jest", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:29.7.0"],\ ["lodash", "npm:4.17.21"],\ - ["mathjs", "npm:14.0.1"],\ - ["moment", "npm:2.30.1"],\ + ["mockdate", "npm:3.0.5"],\ ["pre-commit", "npm:1.2.2"],\ ["prettier", "npm:3.4.2"],\ - ["ramda", "npm:0.30.1"],\ ["showdown", "npm:2.1.0"],\ ["ts-jest", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:29.2.5"],\ ["typescript", "patch:typescript@npm%3A5.7.2#optional!builtin::version=5.7.2&hash=5786d5"],\ @@ -82,9 +79,8 @@ const RAW_RUNTIME_STATE = ["@awell-health/awell-score", "workspace:."],\ ["@types/cpx", "npm:1.5.5"],\ ["@types/jest", "npm:29.5.14"],\ - ["@types/lodash", "npm:4.17.13"],\ - ["@types/node", "npm:18.19.68"],\ - ["@types/ramda", "npm:0.28.25"],\ + ["@types/lodash", "npm:4.17.14"],\ + ["@types/node", "npm:18.19.69"],\ ["@types/showdown", "npm:2.0.6"],\ ["@typescript-eslint/eslint-plugin", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:8.19.0"],\ ["@typescript-eslint/parser", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:8.19.0"],\ @@ -94,11 +90,9 @@ const RAW_RUNTIME_STATE = ["husky", "npm:9.1.7"],\ ["jest", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:29.7.0"],\ ["lodash", "npm:4.17.21"],\ - ["mathjs", "npm:14.0.1"],\ - ["moment", "npm:2.30.1"],\ + ["mockdate", "npm:3.0.5"],\ ["pre-commit", "npm:1.2.2"],\ ["prettier", "npm:3.4.2"],\ - ["ramda", "npm:0.30.1"],\ ["showdown", "npm:2.1.0"],\ ["ts-jest", "virtual:c11cbab1df73e7032a6d8bcafb5c58a4c11fb78ba80ef895601a81a15c29f5b343c43e035b66a1214c24a4f6d3e38f8ccc02d9319d36f49c292198fca205d412#npm:29.2.5"],\ ["typescript", "patch:typescript@npm%3A5.7.2#optional!builtin::version=5.7.2&hash=5786d5"],\ @@ -874,16 +868,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@babel/runtime", [\ - ["npm:7.26.0", {\ - "packageLocation": "./.yarn/cache/@babel-runtime-npm-7.26.0-9afa3c4ef6-9f4ea1c1d5.zip/node_modules/@babel/runtime/",\ - "packageDependencies": [\ - ["@babel/runtime", "npm:7.26.0"],\ - ["regenerator-runtime", "npm:0.14.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@babel/template", [\ ["npm:7.25.9", {\ "packageLocation": "./.yarn/cache/@babel-template-npm-7.25.9-d903b7b6d5-e861180881.zip/node_modules/@babel/template/",\ @@ -1140,7 +1124,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@jest/console", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["chalk", "npm:4.1.2"],\ ["jest-message-util", "npm:29.7.0"],\ ["jest-util", "npm:29.7.0"],\ @@ -1166,7 +1150,7 @@ const RAW_RUNTIME_STATE = ["@jest/test-result", "npm:29.7.0"],\ ["@jest/transform", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["@types/node-notifier", null],\ ["ansi-escapes", "npm:4.3.2"],\ ["chalk", "npm:4.1.2"],\ @@ -1206,7 +1190,7 @@ const RAW_RUNTIME_STATE = ["@jest/environment", "npm:29.7.0"],\ ["@jest/fake-timers", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["jest-mock", "npm:29.7.0"]\ ],\ "linkType": "HARD"\ @@ -1240,7 +1224,7 @@ const RAW_RUNTIME_STATE = ["@jest/fake-timers", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ ["@sinonjs/fake-timers", "npm:10.3.0"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["jest-message-util", "npm:29.7.0"],\ ["jest-mock", "npm:29.7.0"],\ ["jest-util", "npm:29.7.0"]\ @@ -1279,7 +1263,7 @@ const RAW_RUNTIME_STATE = ["@jest/transform", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ ["@jridgewell/trace-mapping", "npm:0.3.25"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["@types/node-notifier", null],\ ["chalk", "npm:4.1.2"],\ ["collect-v8-coverage", "npm:1.0.2"],\ @@ -1387,7 +1371,7 @@ const RAW_RUNTIME_STATE = ["@jest/schemas", "npm:29.6.3"],\ ["@types/istanbul-lib-coverage", "npm:2.0.6"],\ ["@types/istanbul-reports", "npm:3.0.4"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["@types/yargs", "npm:17.0.33"],\ ["chalk", "npm:4.1.2"]\ ],\ @@ -1608,7 +1592,7 @@ const RAW_RUNTIME_STATE = ["@types/cacheable-request", "npm:6.0.3"],\ ["@types/http-cache-semantics", "npm:4.0.4"],\ ["@types/keyv", "npm:3.1.4"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["@types/responselike", "npm:1.0.3"]\ ],\ "linkType": "HARD"\ @@ -1619,7 +1603,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/@types-cpx-npm-1.5.5-797310dd27-3fc715ebc5.zip/node_modules/@types/cpx/",\ "packageDependencies": [\ ["@types/cpx", "npm:1.5.5"],\ - ["@types/node", "npm:22.10.2"]\ + ["@types/node", "npm:22.10.5"]\ ],\ "linkType": "HARD"\ }]\ @@ -1647,7 +1631,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/@types-graceful-fs-npm-4.1.9-ebd697fe83-79d746a8f0.zip/node_modules/@types/graceful-fs/",\ "packageDependencies": [\ ["@types/graceful-fs", "npm:4.1.9"],\ - ["@types/node", "npm:22.10.2"]\ + ["@types/node", "npm:22.10.5"]\ ],\ "linkType": "HARD"\ }]\ @@ -1715,54 +1699,44 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/@types-keyv-npm-3.1.4-a8082ea56b-e009a2bfb5.zip/node_modules/@types/keyv/",\ "packageDependencies": [\ ["@types/keyv", "npm:3.1.4"],\ - ["@types/node", "npm:22.10.2"]\ + ["@types/node", "npm:22.10.5"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/lodash", [\ - ["npm:4.17.13", {\ - "packageLocation": "./.yarn/cache/@types-lodash-npm-4.17.13-ec44e3530a-ddb34e2081.zip/node_modules/@types/lodash/",\ + ["npm:4.17.14", {\ + "packageLocation": "./.yarn/cache/@types-lodash-npm-4.17.14-6b38705727-6ee40725f3.zip/node_modules/@types/lodash/",\ "packageDependencies": [\ - ["@types/lodash", "npm:4.17.13"]\ + ["@types/lodash", "npm:4.17.14"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/node", [\ - ["npm:18.19.68", {\ - "packageLocation": "./.yarn/cache/@types-node-npm-18.19.68-d1900b5d2e-024a4a8eec.zip/node_modules/@types/node/",\ + ["npm:18.19.69", {\ + "packageLocation": "./.yarn/cache/@types-node-npm-18.19.69-17bc8afded-fe34976dd1.zip/node_modules/@types/node/",\ "packageDependencies": [\ - ["@types/node", "npm:18.19.68"],\ + ["@types/node", "npm:18.19.69"],\ ["undici-types", "npm:5.26.5"]\ ],\ "linkType": "HARD"\ }],\ - ["npm:22.10.2", {\ - "packageLocation": "./.yarn/cache/@types-node-npm-22.10.2-572466b048-451adfefed.zip/node_modules/@types/node/",\ + ["npm:22.10.5", {\ + "packageLocation": "./.yarn/cache/@types-node-npm-22.10.5-cd9f5f929b-a5366961ff.zip/node_modules/@types/node/",\ "packageDependencies": [\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["undici-types", "npm:6.20.0"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@types/ramda", [\ - ["npm:0.28.25", {\ - "packageLocation": "./.yarn/cache/@types-ramda-npm-0.28.25-bf3273fca9-507400af2b.zip/node_modules/@types/ramda/",\ - "packageDependencies": [\ - ["@types/ramda", "npm:0.28.25"],\ - ["ts-toolbelt", "npm:6.15.5"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@types/responselike", [\ ["npm:1.0.3", {\ "packageLocation": "./.yarn/cache/@types-responselike-npm-1.0.3-de0150f03d-6ac4b35723.zip/node_modules/@types/responselike/",\ "packageDependencies": [\ ["@types/responselike", "npm:1.0.3"],\ - ["@types/node", "npm:22.10.2"]\ + ["@types/node", "npm:22.10.5"]\ ],\ "linkType": "HARD"\ }]\ @@ -2971,15 +2945,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["complex.js", [\ - ["npm:2.4.2", {\ - "packageLocation": "./.yarn/cache/complex.js-npm-2.4.2-c9d45fff42-089257e0f0.zip/node_modules/complex.js/",\ - "packageDependencies": [\ - ["complex.js", "npm:2.4.2"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["component-emitter", [\ ["npm:1.3.1", {\ "packageLocation": "./.yarn/cache/component-emitter-npm-1.3.1-c2a8131a7e-94550aa462.zip/node_modules/component-emitter/",\ @@ -3149,15 +3114,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["decimal.js", [\ - ["npm:10.4.3", {\ - "packageLocation": "./.yarn/cache/decimal.js-npm-10.4.3-e7d483387c-de663a7bc4.zip/node_modules/decimal.js/",\ - "packageDependencies": [\ - ["decimal.js", "npm:10.4.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["decode-uri-component", [\ ["npm:0.2.2", {\ "packageLocation": "./.yarn/cache/decode-uri-component-npm-0.2.2-e22e2aa917-17a0e5fa40.zip/node_modules/decode-uri-component/",\ @@ -3408,15 +3364,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["escape-latex", [\ - ["npm:1.2.0", {\ - "packageLocation": "./.yarn/cache/escape-latex-npm-1.2.0-1481ca81a7-73a787319f.zip/node_modules/escape-latex/",\ - "packageDependencies": [\ - ["escape-latex", "npm:1.2.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["escape-string-regexp", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/escape-string-regexp-npm-2.0.0-aef69d2a25-9f8a2d5743.zip/node_modules/escape-string-regexp/",\ @@ -3914,15 +3861,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["fraction.js", [\ - ["npm:5.2.1", {\ - "packageLocation": "./.yarn/cache/fraction.js-npm-5.2.1-722e0c258f-ea67897942.zip/node_modules/fraction.js/",\ - "packageDependencies": [\ - ["fraction.js", "npm:5.2.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["fragment-cache", [\ ["npm:0.2.1", {\ "packageLocation": "./.yarn/cache/fragment-cache-npm-0.2.1-407fe74319-1cbbd0b011.zip/node_modules/fragment-cache/",\ @@ -4777,15 +4715,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["javascript-natural-sort", [\ - ["npm:0.7.1", {\ - "packageLocation": "./.yarn/cache/javascript-natural-sort-npm-0.7.1-9018625996-7bf6eab678.zip/node_modules/javascript-natural-sort/",\ - "packageDependencies": [\ - ["javascript-natural-sort", "npm:0.7.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["jest", [\ ["npm:29.7.0", {\ "packageLocation": "./.yarn/cache/jest-npm-29.7.0-d8dd095b81-97023d7844.zip/node_modules/jest/",\ @@ -4833,7 +4762,7 @@ const RAW_RUNTIME_STATE = ["@jest/expect", "npm:29.7.0"],\ ["@jest/test-result", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["chalk", "npm:4.1.2"],\ ["co", "npm:4.6.0"],\ ["dedent", "virtual:f7679858c638e2e5ade31901dd2b1e5007918fdc7d84fefb11f4200f46ba2e43b9d662fb793507b517bb1e725144e51f6d68f60f9f6100fd52144f042f58f0bc#npm:1.5.3"],\ @@ -4901,7 +4830,7 @@ const RAW_RUNTIME_STATE = ["@babel/core", "npm:7.26.0"],\ ["@jest/test-sequencer", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["@types/ts-node", null],\ ["babel-jest", "virtual:876d680c6ca35cf516b7a36df485796c3bb349d8acf02958cf37dde548880bdddae62d2c992853e10fe94f9cd843aeab187d71fcfd7e9f155fcdfcb803ce0d56#npm:29.7.0"],\ ["chalk", "npm:4.1.2"],\ @@ -5014,7 +4943,7 @@ const RAW_RUNTIME_STATE = ["@jest/environment", "npm:29.7.0"],\ ["@jest/fake-timers", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["jest-mock", "npm:29.7.0"],\ ["jest-util", "npm:29.7.0"]\ ],\ @@ -5037,7 +4966,7 @@ const RAW_RUNTIME_STATE = ["jest-haste-map", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ ["@types/graceful-fs", "npm:4.1.9"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["anymatch", "npm:3.1.3"],\ ["fb-watchman", "npm:2.0.2"],\ ["fsevents", "patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1"],\ @@ -5099,7 +5028,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["jest-mock", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["jest-util", "npm:29.7.0"]\ ],\ "linkType": "HARD"\ @@ -5175,7 +5104,7 @@ const RAW_RUNTIME_STATE = ["@jest/test-result", "npm:29.7.0"],\ ["@jest/transform", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["chalk", "npm:4.1.2"],\ ["emittery", "npm:0.13.1"],\ ["graceful-fs", "npm:4.2.11"],\ @@ -5207,7 +5136,7 @@ const RAW_RUNTIME_STATE = ["@jest/test-result", "npm:29.7.0"],\ ["@jest/transform", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["chalk", "npm:4.1.2"],\ ["cjs-module-lexer", "npm:1.4.1"],\ ["collect-v8-coverage", "npm:1.0.2"],\ @@ -5261,7 +5190,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["jest-util", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["chalk", "npm:4.1.2"],\ ["ci-info", "npm:3.9.0"],\ ["graceful-fs", "npm:4.2.11"],\ @@ -5292,7 +5221,7 @@ const RAW_RUNTIME_STATE = ["jest-watcher", "npm:29.7.0"],\ ["@jest/test-result", "npm:29.7.0"],\ ["@jest/types", "npm:29.6.3"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["ansi-escapes", "npm:4.3.2"],\ ["chalk", "npm:4.1.2"],\ ["emittery", "npm:0.13.1"],\ @@ -5307,7 +5236,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/jest-worker-npm-29.7.0-4d3567fed6-364cbaef00.zip/node_modules/jest-worker/",\ "packageDependencies": [\ ["jest-worker", "npm:29.7.0"],\ - ["@types/node", "npm:22.10.2"],\ + ["@types/node", "npm:22.10.5"],\ ["jest-util", "npm:29.7.0"],\ ["merge-stream", "npm:2.0.0"],\ ["supports-color", "npm:8.1.1"]\ @@ -5636,24 +5565,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["mathjs", [\ - ["npm:14.0.1", {\ - "packageLocation": "./.yarn/cache/mathjs-npm-14.0.1-ce17ee391f-a3eed2f2b8.zip/node_modules/mathjs/",\ - "packageDependencies": [\ - ["mathjs", "npm:14.0.1"],\ - ["@babel/runtime", "npm:7.26.0"],\ - ["complex.js", "npm:2.4.2"],\ - ["decimal.js", "npm:10.4.3"],\ - ["escape-latex", "npm:1.2.0"],\ - ["fraction.js", "npm:5.2.1"],\ - ["javascript-natural-sort", "npm:0.7.1"],\ - ["seedrandom", "npm:3.0.5"],\ - ["tiny-emitter", "npm:2.1.0"],\ - ["typed-function", "npm:4.2.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["merge-stream", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/merge-stream-npm-2.0.0-2ac83efea5-6fa4dcc8d8.zip/node_modules/merge-stream/",\ @@ -5915,11 +5826,11 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["moment", [\ - ["npm:2.30.1", {\ - "packageLocation": "./.yarn/cache/moment-npm-2.30.1-1c51a5c631-ae42d876d4.zip/node_modules/moment/",\ + ["mockdate", [\ + ["npm:3.0.5", {\ + "packageLocation": "./.yarn/cache/mockdate-npm-3.0.5-16a4ff9e8b-ff74f43f56.zip/node_modules/mockdate/",\ "packageDependencies": [\ - ["moment", "npm:2.30.1"]\ + ["mockdate", "npm:3.0.5"]\ ],\ "linkType": "HARD"\ }]\ @@ -6515,15 +6426,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["ramda", [\ - ["npm:0.30.1", {\ - "packageLocation": "./.yarn/cache/ramda-npm-0.30.1-b62811823d-f3e1a7bc11.zip/node_modules/ramda/",\ - "packageDependencies": [\ - ["ramda", "npm:0.30.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["randomatic", [\ ["npm:3.1.1", {\ "packageLocation": "./.yarn/cache/randomatic-npm-3.1.1-149177375b-fd7517e784.zip/node_modules/randomatic/",\ @@ -6580,13 +6482,6 @@ const RAW_RUNTIME_STATE = ["regenerator-runtime", "npm:0.11.1"]\ ],\ "linkType": "HARD"\ - }],\ - ["npm:0.14.1", {\ - "packageLocation": "./.yarn/cache/regenerator-runtime-npm-0.14.1-a6c97c609a-5db3161abb.zip/node_modules/regenerator-runtime/",\ - "packageDependencies": [\ - ["regenerator-runtime", "npm:0.14.1"]\ - ],\ - "linkType": "HARD"\ }]\ ]],\ ["regex-cache", [\ @@ -6803,15 +6698,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["seedrandom", [\ - ["npm:3.0.5", {\ - "packageLocation": "./.yarn/cache/seedrandom-npm-3.0.5-6946e8f8db-acad5e516c.zip/node_modules/seedrandom/",\ - "packageDependencies": [\ - ["seedrandom", "npm:3.0.5"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["semver", [\ ["npm:6.3.1", {\ "packageLocation": "./.yarn/cache/semver-npm-6.3.1-bcba31fdbe-1ef3a85bd0.zip/node_modules/semver/",\ @@ -7282,15 +7168,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["tiny-emitter", [\ - ["npm:2.1.0", {\ - "packageLocation": "./.yarn/cache/tiny-emitter-npm-2.1.0-2a4d94f487-75633f4de4.zip/node_modules/tiny-emitter/",\ - "packageDependencies": [\ - ["tiny-emitter", "npm:2.1.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["tinylogic", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/tinylogic-npm-2.0.0-700fcc2fe0-6467b1ed9b.zip/node_modules/tinylogic/",\ @@ -7437,15 +7314,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["ts-toolbelt", [\ - ["npm:6.15.5", {\ - "packageLocation": "./.yarn/cache/ts-toolbelt-npm-6.15.5-e42f89942f-1816b11f6a.zip/node_modules/ts-toolbelt/",\ - "packageDependencies": [\ - ["ts-toolbelt", "npm:6.15.5"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["tslib", [\ ["npm:2.8.1", {\ "packageLocation": "./.yarn/cache/tslib-npm-2.8.1-66590b21b8-3e2e043d5c.zip/node_modules/tslib/",\ @@ -7501,15 +7369,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["typed-function", [\ - ["npm:4.2.1", {\ - "packageLocation": "./.yarn/cache/typed-function-npm-4.2.1-68f0b6c302-2218d6e4a5.zip/node_modules/typed-function/",\ - "packageDependencies": [\ - ["typed-function", "npm:4.2.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["typedarray", [\ ["npm:0.0.6", {\ "packageLocation": "./.yarn/cache/typedarray-npm-0.0.6-37638b2241-2cc1bcf7d8.zip/node_modules/typedarray/",\ diff --git a/.yarn/cache/@babel-runtime-npm-7.26.0-9afa3c4ef6-9f4ea1c1d5.zip b/.yarn/cache/@babel-runtime-npm-7.26.0-9afa3c4ef6-9f4ea1c1d5.zip deleted file mode 100644 index 59f3301..0000000 Binary files a/.yarn/cache/@babel-runtime-npm-7.26.0-9afa3c4ef6-9f4ea1c1d5.zip and /dev/null differ diff --git a/.yarn/cache/@types-lodash-npm-4.17.13-ec44e3530a-ddb34e2081.zip b/.yarn/cache/@types-lodash-npm-4.17.14-6b38705727-6ee40725f3.zip similarity index 89% rename from .yarn/cache/@types-lodash-npm-4.17.13-ec44e3530a-ddb34e2081.zip rename to .yarn/cache/@types-lodash-npm-4.17.14-6b38705727-6ee40725f3.zip index d833b2c..e1c1ed3 100644 Binary files a/.yarn/cache/@types-lodash-npm-4.17.13-ec44e3530a-ddb34e2081.zip and b/.yarn/cache/@types-lodash-npm-4.17.14-6b38705727-6ee40725f3.zip differ diff --git a/.yarn/cache/@types-node-npm-18.19.68-d1900b5d2e-024a4a8eec.zip b/.yarn/cache/@types-node-npm-18.19.69-17bc8afded-fe34976dd1.zip similarity index 97% rename from .yarn/cache/@types-node-npm-18.19.68-d1900b5d2e-024a4a8eec.zip rename to .yarn/cache/@types-node-npm-18.19.69-17bc8afded-fe34976dd1.zip index 2302a3c..5b5c981 100644 Binary files a/.yarn/cache/@types-node-npm-18.19.68-d1900b5d2e-024a4a8eec.zip and b/.yarn/cache/@types-node-npm-18.19.69-17bc8afded-fe34976dd1.zip differ diff --git a/.yarn/cache/@types-node-npm-22.10.2-572466b048-451adfefed.zip b/.yarn/cache/@types-node-npm-22.10.5-cd9f5f929b-a5366961ff.zip similarity index 94% rename from .yarn/cache/@types-node-npm-22.10.2-572466b048-451adfefed.zip rename to .yarn/cache/@types-node-npm-22.10.5-cd9f5f929b-a5366961ff.zip index bce0200..a4e1773 100644 Binary files a/.yarn/cache/@types-node-npm-22.10.2-572466b048-451adfefed.zip and b/.yarn/cache/@types-node-npm-22.10.5-cd9f5f929b-a5366961ff.zip differ diff --git a/.yarn/cache/@types-ramda-npm-0.28.25-bf3273fca9-507400af2b.zip b/.yarn/cache/@types-ramda-npm-0.28.25-bf3273fca9-507400af2b.zip deleted file mode 100644 index 259ff36..0000000 Binary files a/.yarn/cache/@types-ramda-npm-0.28.25-bf3273fca9-507400af2b.zip and /dev/null differ diff --git a/.yarn/cache/complex.js-npm-2.4.2-c9d45fff42-089257e0f0.zip b/.yarn/cache/complex.js-npm-2.4.2-c9d45fff42-089257e0f0.zip deleted file mode 100644 index 6f673e0..0000000 Binary files a/.yarn/cache/complex.js-npm-2.4.2-c9d45fff42-089257e0f0.zip and /dev/null differ diff --git a/.yarn/cache/decimal.js-npm-10.4.3-e7d483387c-de663a7bc4.zip b/.yarn/cache/decimal.js-npm-10.4.3-e7d483387c-de663a7bc4.zip deleted file mode 100644 index 83e95f1..0000000 Binary files a/.yarn/cache/decimal.js-npm-10.4.3-e7d483387c-de663a7bc4.zip and /dev/null differ diff --git a/.yarn/cache/escape-latex-npm-1.2.0-1481ca81a7-73a787319f.zip b/.yarn/cache/escape-latex-npm-1.2.0-1481ca81a7-73a787319f.zip deleted file mode 100644 index ae599c2..0000000 Binary files a/.yarn/cache/escape-latex-npm-1.2.0-1481ca81a7-73a787319f.zip and /dev/null differ diff --git a/.yarn/cache/fraction.js-npm-5.2.1-722e0c258f-ea67897942.zip b/.yarn/cache/fraction.js-npm-5.2.1-722e0c258f-ea67897942.zip deleted file mode 100644 index 4353bc1..0000000 Binary files a/.yarn/cache/fraction.js-npm-5.2.1-722e0c258f-ea67897942.zip and /dev/null differ diff --git a/.yarn/cache/javascript-natural-sort-npm-0.7.1-9018625996-7bf6eab678.zip b/.yarn/cache/javascript-natural-sort-npm-0.7.1-9018625996-7bf6eab678.zip deleted file mode 100644 index 0cbedd3..0000000 Binary files a/.yarn/cache/javascript-natural-sort-npm-0.7.1-9018625996-7bf6eab678.zip and /dev/null differ diff --git a/.yarn/cache/mathjs-npm-14.0.1-ce17ee391f-a3eed2f2b8.zip b/.yarn/cache/mathjs-npm-14.0.1-ce17ee391f-a3eed2f2b8.zip deleted file mode 100644 index f517529..0000000 Binary files a/.yarn/cache/mathjs-npm-14.0.1-ce17ee391f-a3eed2f2b8.zip and /dev/null differ diff --git a/.yarn/cache/mockdate-npm-3.0.5-16a4ff9e8b-ff74f43f56.zip b/.yarn/cache/mockdate-npm-3.0.5-16a4ff9e8b-ff74f43f56.zip new file mode 100644 index 0000000..51f7e9c Binary files /dev/null and b/.yarn/cache/mockdate-npm-3.0.5-16a4ff9e8b-ff74f43f56.zip differ diff --git a/.yarn/cache/moment-npm-2.30.1-1c51a5c631-ae42d876d4.zip b/.yarn/cache/moment-npm-2.30.1-1c51a5c631-ae42d876d4.zip deleted file mode 100644 index 8f1438a..0000000 Binary files a/.yarn/cache/moment-npm-2.30.1-1c51a5c631-ae42d876d4.zip and /dev/null differ diff --git a/.yarn/cache/ramda-npm-0.30.1-b62811823d-f3e1a7bc11.zip b/.yarn/cache/ramda-npm-0.30.1-b62811823d-f3e1a7bc11.zip deleted file mode 100644 index d76ea55..0000000 Binary files a/.yarn/cache/ramda-npm-0.30.1-b62811823d-f3e1a7bc11.zip and /dev/null differ diff --git a/.yarn/cache/regenerator-runtime-npm-0.14.1-a6c97c609a-5db3161abb.zip b/.yarn/cache/regenerator-runtime-npm-0.14.1-a6c97c609a-5db3161abb.zip deleted file mode 100644 index 176e755..0000000 Binary files a/.yarn/cache/regenerator-runtime-npm-0.14.1-a6c97c609a-5db3161abb.zip and /dev/null differ diff --git a/.yarn/cache/seedrandom-npm-3.0.5-6946e8f8db-acad5e516c.zip b/.yarn/cache/seedrandom-npm-3.0.5-6946e8f8db-acad5e516c.zip deleted file mode 100644 index 7189e21..0000000 Binary files a/.yarn/cache/seedrandom-npm-3.0.5-6946e8f8db-acad5e516c.zip and /dev/null differ diff --git a/.yarn/cache/tiny-emitter-npm-2.1.0-2a4d94f487-75633f4de4.zip b/.yarn/cache/tiny-emitter-npm-2.1.0-2a4d94f487-75633f4de4.zip deleted file mode 100644 index 980fe7b..0000000 Binary files a/.yarn/cache/tiny-emitter-npm-2.1.0-2a4d94f487-75633f4de4.zip and /dev/null differ diff --git a/.yarn/cache/ts-toolbelt-npm-6.15.5-e42f89942f-1816b11f6a.zip b/.yarn/cache/ts-toolbelt-npm-6.15.5-e42f89942f-1816b11f6a.zip deleted file mode 100644 index 5517113..0000000 Binary files a/.yarn/cache/ts-toolbelt-npm-6.15.5-e42f89942f-1816b11f6a.zip and /dev/null differ diff --git a/.yarn/cache/typed-function-npm-4.2.1-68f0b6c302-2218d6e4a5.zip b/.yarn/cache/typed-function-npm-4.2.1-68f0b6c302-2218d6e4a5.zip deleted file mode 100644 index 89e0dd3..0000000 Binary files a/.yarn/cache/typed-function-npm-4.2.1-68f0b6c302-2218d6e4a5.zip and /dev/null differ diff --git a/package.json b/package.json index 0ee9838..b5f6e70 100644 --- a/package.json +++ b/package.json @@ -24,18 +24,14 @@ "license": "ISC", "dependencies": { "lodash": "^4.17.21", - "mathjs": "^14.0.1", - "moment": "^2.30.1", - "ramda": "^0.30.1", "showdown": "^2.1.0", "zod": "^3.24.1" }, "devDependencies": { "@types/cpx": "^1", "@types/jest": "^29.5.14", - "@types/lodash": "^4.14.186", + "@types/lodash": "^4", "@types/node": "^18.7.23", - "@types/ramda": "^0.28.15", "@types/showdown": "^2.0.0", "@typescript-eslint/eslint-plugin": "^8.18.2", "@typescript-eslint/parser": "^8.18.2", @@ -44,6 +40,7 @@ "eslint": "^9.17.0", "husky": "^9.1.7", "jest": "^29.7.0", + "mockdate": "^3.0.5", "pre-commit": "^1.2.2", "prettier": "^3.4.2", "ts-jest": "^29.2.5", diff --git a/src/classes/Score.ts b/src/classes/Score.ts index 9a9d256..3c11b41 100644 --- a/src/classes/Score.ts +++ b/src/classes/Score.ts @@ -4,7 +4,6 @@ import { type ScoreOutputSchemaType, type ScoreType, type CalculateFn, - type CategoryType, type TerminologyType, } from '../types' import { @@ -20,7 +19,7 @@ import { tryCastToStringsArray, tryCastToNumbersArray, } from '../lib/castFunctions' -import _ from 'lodash' +import { mapValues, sample, random, sampleSize, pickBy } from 'lodash' import { simulateDateInput, simulateStringInput } from '../lib/simulation' import { parseToApiResultFormat } from '../lib/parseToApiResultFormat' @@ -207,7 +206,7 @@ export class Score< return input_value } - return _.mapValues(data, castInputToExactType) + return mapValues(data, castInputToExactType) } /** @@ -221,7 +220,7 @@ export class Score< z.infer | null > } { - const simulatedInput = _.mapValues( + const simulatedInput = mapValues( this.inputSchemaAsObject.shape, zodType => { const getZodType = () => { @@ -247,19 +246,19 @@ export class Score< } if (inputType instanceof z.ZodBoolean) { - return _.sample([true, false]) + return sample([true, false]) } if (inputType instanceof z.ZodNumber) { const min = inputType.minValue const max = inputType.maxValue - return _.random(min ?? 0, max ?? 100, false) + return random(min ?? 0, max ?? 100, false) } if (inputType instanceof z.ZodUnion) { const optionValues = inputType.options.map(option => option.value) - return _.sample(optionValues) + return sample(optionValues) } if (inputType instanceof z.ZodArray) { @@ -267,11 +266,8 @@ export class Score< if (itemType instanceof z.ZodUnion) { const optionValues = itemType.options.map(option => option.value) - const randomNumberBetweenOneAndMax = _.random( - 1, - optionValues.length, - ) - return _.sampleSize(optionValues, randomNumberBetweenOneAndMax) + const randomNumberBetweenOneAndMax = random(1, optionValues.length) + return sampleSize(optionValues, randomNumberBetweenOneAndMax) } } @@ -280,7 +276,7 @@ export class Score< ) return { - simulatedInput: _.pickBy(simulatedInput, value => value !== undefined), + simulatedInput: pickBy(simulatedInput, value => value !== undefined), results: this.calculate({ payload: simulatedInput }), } } diff --git a/src/docs/swagger.ts b/src/docs/swagger.ts deleted file mode 100644 index a36c50a..0000000 --- a/src/docs/swagger.ts +++ /dev/null @@ -1,740 +0,0 @@ -export const swaggerDefinition = { - openapi: '3.0.0', - info: { - title: 'Awell Score API', - description: - 'A RESTful API to browse, execute and simulate calculations available in the Awell Score Suite.', - version: '1.0', - contact: { - name: 'Awell Health', - url: 'https://awell.health', - email: 'nick@awellhealth.com', - }, - }, - servers: [ - { - description: 'Awell Score - Development', - url: 'https://score-api.development.awellhealth.com', - }, - { - description: 'Awell Score - Staging', - url: 'https://score-api.staging.awellhealth.com', - }, - ], - tags: [ - { - name: 'Calculations', - description: '', - externalDocs: { - description: 'Visit Awell Score Playground', - url: 'https://score.staging.awellhealth.com', - }, - }, - ], - components: { - schemas: { - Calculation: { - type: 'object', - required: [ - 'calculation_id', - 'calculation_name', - 'calculation_description', - 'calculation_blueprint', - 'is_private', - ], - properties: { - calculation_id: { - type: 'string', - }, - calculation_name: { - $ref: '#/components/schemas/label', - }, - calculation_description: { - $ref: '#/components/schemas/label', - }, - calculation_blueprint: { - type: 'object', - required: ['input_definition', 'output_definition'], - properties: { - input_definition: { - type: 'array', - items: { - $ref: '#/components/schemas/calculationParameter', - }, - }, - output_defintion: { - type: 'array', - items: { - $ref: '#/components/schemas/calculationOutputDefinition', - }, - }, - }, - }, - is_private: { - type: 'boolean', - }, - }, - }, - CalculationResult: { - type: 'object', - required: ['subresult_id', 'label', 'result', 'status'], - properties: { - subresult_id: { - type: 'string', - }, - label: { $ref: '#/components/schemas/label' }, - result: { - oneOf: [ - { - type: 'string', - }, - { - type: 'integer', - }, - { - type: 'boolean', - }, - ], - }, - unit: { - $ref: '#/components/schemas/label', - }, - interpretation: { - $ref: '#/components/schemas/label', - }, - status: { - type: 'string', - enum: ['CALCULATED', 'NOT APPLICABLE', 'MISSING'], - }, - }, - }, - label: { - type: 'object', - required: ['en'], - properties: { - en: { - type: 'string', - }, - nl: { - type: 'string', - }, - fr: { - type: 'string', - }, - de: { - type: 'string', - }, - }, - }, - booleanInputType: { - type: 'object', - required: ['type'], - properties: { - type: { - type: 'string', - enum: ['boolean'], - }, - allowed_answers: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'boolean', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - }, - }, - dateInputType: { - type: 'object', - required: ['type'], - properties: { - type: { - type: 'string', - enum: ['date'], - }, - }, - }, - numberInputType: { - type: 'object', - required: ['type'], - properties: { - type: { - type: 'string', - enum: ['number'], - }, - allowed_answers: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'number', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - range: { - type: 'object', - required: ['min', 'max'], - properties: { - min: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'number', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - max: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'number', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - }, - }, - }, - }, - numbersArrayInputType: { - type: 'object', - required: ['type', 'allowed_answers'], - properties: { - type: { - type: 'string', - enum: ['numbers_array'], - }, - allowed_answers: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'number', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - }, - }, - stringInputType: { - type: 'object', - required: ['type'], - properties: { - type: { - type: 'string', - enum: ['string'], - }, - allowed_answers: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'string', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - }, - }, - stringsArrayInputType: { - type: 'object', - required: ['type', 'allowed_answers'], - properties: { - type: { - type: 'string', - enum: ['strings_array'], - }, - allowed_answers: { - type: 'object', - required: ['value'], - properties: { - value: { - type: 'string', - }, - label: { - $ref: '#/components/schemas/label', - }, - }, - }, - }, - }, - calculationOutputDefinition: { - type: 'object', - required: ['subresult_id', 'label', 'type'], - properties: { - subresult_id: { - type: 'string', - }, - label: { $ref: '#/components/schemas/label' }, - type: { - type: 'string', - enum: ['date', 'boolean', 'string', 'number'], - }, - unit: { $ref: '#/components/schemas/label' }, - interpretation: { $ref: '#/components/schemas/label' }, - }, - }, - calculationParameter: { - type: 'object', - required: ['id', 'input_type'], - properties: { - id: { - type: 'string', - }, - label: { $ref: '#/components/schemas/label' }, - type: { - oneOf: [ - { - $ref: '#/components/schemas/booleanInputType', - }, - { - $ref: '#/components/schemas/dateInputType', - }, - { - $ref: '#/components/schemas/numberInputType', - }, - { - $ref: '#/components/schemas/numbersArrayInputType', - }, - { - $ref: '#/components/schemas/stringInputType', - }, - { - $ref: '#/components/schemas/stringsArrayInputType', - }, - ], - }, - info: { - $ref: '#/components/schemas/label', - }, - format: { - type: 'string', - }, - }, - }, - calculationNotFound: { - type: 'object', - required: ['message'], - properties: { - error: { - type: 'object', - required: ['message'], - properties: { - message: { - type: 'string', - }, - }, - }, - }, - }, - }, - }, - paths: { - '/v1/calculations': { - get: { - tags: ['Calculations'], - summary: 'Returns all calculations in our library', - description: - 'Returns all available calculations in the Awell Calculation Suite Library', - responses: { - '200': { - description: 'When the calculations can be successfully returned.', - content: { - 'application/json': { - schema: { - type: 'array', - items: { - $ref: '#/components/schemas/Calculation', - }, - }, - }, - }, - }, - '500': { - description: - 'When something went wrong while getting all the calculations.', - content: { - 'application/json': { - schema: { - type: 'object', - required: ['error'], - properties: { - error: { - type: 'object', - }, - }, - }, - }, - }, - }, - }, - }, - post: { - tags: ['Calculations'], - summary: 'Execute a calculation', - description: 'Execute a single calculation', - requestBody: { - content: { - 'application/json': { - schema: { - type: 'object', - required: ['calculation_id'], - properties: { - calculation_id: { - type: 'string', - }, - calculation_input: { - type: 'object', - additionalProperties: { - oneOf: [ - { - type: 'string', - }, - { - type: 'integer', - }, - ], - }, - }, - meta_data: { - type: 'object', - additionalProperties: { - oneOf: [ - { - type: 'string', - }, - { - type: 'number', - }, - { - type: 'integer', - }, - { - type: 'boolean', - }, - ], - }, - }, - }, - }, - examples: { - bmi: { - summary: 'BMI', - value: { - calculation_id: 'bmi', - calculation_input: { - height: 170, - weight: 75, - }, - meta_data: { - sending_system_request_id: - 'an_identifier_from_the_sending_system', - meta_data_is_optional: 'add_whatever_parameters_you_want', - }, - }, - }, - start_back_screening_tool: { - summary: 'Start Back Screening Tool', - value: { - calculation_id: 'start_back_screening_tool', - calculation_input: { - Q01: 1, - Q02: 0, - Q03: 1, - Q04: 1, - Q05: 1, - Q06: 1, - Q07: 1, - Q08: 0, - Q09: 3, - }, - }, - }, - }, - }, - }, - }, - responses: { - '200': { - description: - 'Returns a list of results for the executed calculation.', - content: { - 'application/json': { - schema: { - type: 'array', - items: { $ref: '#/components/schemas/CalculationResult' }, - }, - }, - }, - }, - '404': { - description: - 'When the calculation you want to execute could not be found.', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/calculationNotFound', - }, - }, - }, - }, - '500': { - description: - 'When something went wrong while executing the calculations', - content: { - 'application/json': { - schema: { - type: 'object', - required: ['error'], - properties: { - error: { - type: 'object', - }, - }, - }, - }, - }, - }, - }, - }, - }, - '/v1/calculations/search': { - get: { - tags: ['Calculations'], - summary: 'Search for a calculation', - description: - 'Search for a calculation based on the identifier of the calculation.', - parameters: [ - { - name: 'calculation_name', - in: 'query', - description: 'Name of the calculation you want to search for', - required: true, - schema: { - type: 'string', - }, - examples: { - bmi: { - summary: 'BMI', - value: 'bmi', - }, - start_back_screening_tool: { - summary: 'Start Back Screening Tool', - value: 'start_back_screening_tool', - }, - }, - }, - ], - responses: { - '200': { - description: - 'Will return a list of calculations that matches the given search parameter.', - content: { - 'application/json': { - schema: { - type: 'array', - items: { - $ref: '#/components/schemas/Calculation', - }, - }, - }, - }, - }, - '400': { - description: 'When the search query was invalid.', - content: { - 'application/json': { - schema: { - type: 'object', - required: ['error'], - properties: { - error: { - type: 'object', - }, - }, - }, - }, - }, - }, - '500': { - description: - 'When something went wrong while searching calculations.', - content: { - 'application/json': { - schema: { - type: 'object', - required: ['error'], - properties: { - error: { - type: 'object', - }, - }, - }, - }, - }, - }, - }, - }, - }, - '/v1/calculations/{calculation_id}': { - get: { - tags: ['Calculations'], - summary: 'Returns one calculation', - description: - 'Get a specific calculation based on the id of the calculation.', - parameters: [ - { - name: 'calculation_id', - in: 'path', - description: 'Identifier of the calculation you want to retrieve.', - required: true, - schema: { - type: 'string', - }, - examples: { - bmi: { - summary: 'BMI', - value: 'bmi', - }, - start_back_screening_tool: { - summary: 'Start Back Screening Tool', - value: 'start_back_screening_tool', - }, - }, - }, - ], - responses: { - '200': { - description: 'Will return a single calculation.', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Calculation', - }, - }, - }, - }, - '404': { - description: 'When the calculation could not be found.', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/calculationNotFound', - }, - }, - }, - }, - '500': { - description: 'When something went while getting the calculations', - content: { - 'application/json': { - schema: { - type: 'object', - required: ['error'], - properties: { - error: { - type: 'object', - }, - }, - }, - }, - }, - }, - }, - }, - }, - '/v1/calculations/simulate/{calculation_id}': { - get: { - tags: ['Calculations'], - summary: 'Simulate a calculation', - description: - 'Simulate a calculation. A simulation will randomly generate input for the calculation and based on the simulated input the results will be calculated.', - parameters: [ - { - name: 'calculation_id', - in: 'path', - description: 'Identifier of the calculation you want to simulate.', - required: true, - schema: { - type: 'string', - }, - examples: { - bmi: { - summary: 'BMI', - value: 'bmi', - }, - start_back_screening_tool: { - summary: 'Start Back Screening Tool', - value: 'start_back_screening_tool', - }, - }, - }, - ], - responses: { - '200': { - description: '', - content: { - 'application/json': { - schema: { - type: 'object', - required: [ - 'simulated_calculation_input', - 'simulated_calculation_results', - ], - properties: { - simulated_calculation_input: { - type: 'object', - additionalProperties: { - oneOf: [ - { - type: 'string', - }, - { - type: 'integer', - }, - ], - }, - }, - simulated_calculation_results: { - type: 'array', - items: { $ref: '#/components/schemas/CalculationResult' }, - }, - }, - }, - }, - }, - }, - '404': { - description: - 'When the calculation you want to simulate could not be found.', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/calculationNotFound', - }, - }, - }, - }, - }, - }, - }, - }, -} diff --git a/src/lib/parseToApiSchema/awell/lib/inputSchemaToApiInputSchema/inputSchemaToApiInputSchema.ts b/src/lib/parseToApiSchema/awell/lib/inputSchemaToApiInputSchema/inputSchemaToApiInputSchema.ts index 048f71e..fa3283e 100644 --- a/src/lib/parseToApiSchema/awell/lib/inputSchemaToApiInputSchema/inputSchemaToApiInputSchema.ts +++ b/src/lib/parseToApiSchema/awell/lib/inputSchemaToApiInputSchema/inputSchemaToApiInputSchema.ts @@ -1,5 +1,5 @@ import { z } from 'zod' -import _, { isNil } from 'lodash' +import { isNil } from 'lodash' import { LabelType, ScoreInputSchemaType, diff --git a/src/lib/shared.ts b/src/lib/shared.ts index 807423d..9f32e48 100644 --- a/src/lib/shared.ts +++ b/src/lib/shared.ts @@ -1,4 +1,4 @@ -import _ from 'lodash' +import { isEmpty } from 'lodash' export const is_numeric = (val: unknown): boolean => typeof val === 'number' && !Number.isNaN(val) @@ -15,7 +15,7 @@ type RemoveUndefined = { export const areAllValuesDefined = >( data: T, ): data is RemoveUndefined => { - if (_.isEmpty(data)) { + if (isEmpty(data)) { return false } return Object.values(data).every(value => value !== undefined) diff --git a/src/lib/simulation/simulateStringInput.ts b/src/lib/simulation/simulateStringInput.ts index ae58e49..f9de993 100644 --- a/src/lib/simulation/simulateStringInput.ts +++ b/src/lib/simulation/simulateStringInput.ts @@ -1,6 +1,4 @@ -// import R from 'ramda' - -import _ from 'lodash' +import { sample } from 'lodash' export const simulateStringInput = (): string => { const DEFAULT_SIMULATION = [ @@ -11,5 +9,5 @@ export const simulateStringInput = (): string => { 'Tony’s turtle told tall tales', ] as const - return _.sample(DEFAULT_SIMULATION) + return sample(DEFAULT_SIMULATION) } diff --git a/src/scores/10_meter_walk_test/10_meter_walk_test.ts b/src/scores/10_meter_walk_test/10_meter_walk_test.ts index 3d1c3cb..4c05b94 100644 --- a/src/scores/10_meter_walk_test/10_meter_walk_test.ts +++ b/src/scores/10_meter_walk_test/10_meter_walk_test.ts @@ -1,10 +1,9 @@ -import R from 'ramda' -import { round } from 'mathjs' import { ScoreType } from '../../types' import { TEN_METER_WALK_TEST_INPUTS, TEN_METER_WALK_TEST_OUTPUT, } from './definition' +import { sum, round, mean } from 'lodash' export const ten_meter_walk_test: ScoreType< typeof TEN_METER_WALK_TEST_INPUTS, @@ -16,12 +15,14 @@ export const ten_meter_walk_test: ScoreType< outputSchema: TEN_METER_WALK_TEST_OUTPUT, calculate: ({ data }) => { const DISTANCE_PER_TRIAL = 10 // 10 meters per trial - const TOTAL_DISTANCE = Object.values(data).length * DISTANCE_PER_TRIAL - const TOTAL_TIME = R.sum(Object.values(data)) + const TOTAL_DISTANCE = + Object.values(data).filter(v => v !== undefined).length * + DISTANCE_PER_TRIAL + const TOTAL_TIME = sum(Object.values(data)) const ROUND_TO = 2 - const MEAN_IN_SECONDS_RESULT = round(R.mean(Object.values(data)), ROUND_TO) + const MEAN_IN_SECONDS_RESULT = round(mean(Object.values(data)), ROUND_TO) /** * Calculate average speed in meters per second diff --git a/src/scores/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.test.ts b/src/scores/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.test.ts new file mode 100644 index 0000000..398d48f --- /dev/null +++ b/src/scores/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.test.ts @@ -0,0 +1,103 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + best_response, + random_response, + worst_response, +} from './__testdata__/CHA2DS2_VASc_Score_test_responses' +import { CHA2DS2_VASc_Score } from './CHA2DS2_VASc_Score' + +const BEST_SCORE = 0 +const WORST_SCORE = 9 + +const calculation = new Score(CHA2DS2_VASc_Score) + +describe('CHA2DS2_VASc_Score', function () { + it('CHA2DS2_VASc_Score calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('CHA2DS2_VASc_Score') + }) + + describe('basic assumptions', function () { + const outcome = calculation.calculate({ payload: best_response }) + + it('should return 1 calculation result', function () { + expect(Object.keys(outcome).length).toEqual(1) + }) + + it('should have the expected calculation result ids', function () { + const EXPECTED_CALCULATION_ID = ['CHA2DS2_VASC_SCORE'] + + 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 = [ + '1_AGE', + '2_SEX', + '3_CHF_HISTORY', + '4_HYPERTENSION_HISTORY', + '5_STROKE_TIA_THROMBOEMBOLISM_HISTORY', + '6_VASCULAR_DISEASE_HISTORY', + '7_DIABETES_HISTORY', + ] + + const configured_input_ids = Object.keys(calculation.inputSchema) + 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 ZodError', function () { + expect(() => + calculation.calculate({ + payload: { + '7_DIABETES_HISTORY': 3, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with an empty response', function () { + it('should throw a ZodError', function () { + expect(() => + calculation.calculate({ + payload: {}, + }), + ).toThrow(ZodError) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with the best response', function () { + const outcome = calculation.calculate({ payload: best_response }) + + it('should return the best score', function () { + expect(outcome.CHA2DS2_VASC_SCORE).toEqual(BEST_SCORE) + }) + }) + describe('when called with the worst response', function () { + const outcome = calculation.calculate({ payload: worst_response }) + + it('should return the worst "Patient interview" score', function () { + expect(outcome.CHA2DS2_VASC_SCORE).toEqual(WORST_SCORE) + }) + }) + + describe('when called with a random response', function () { + const outcome = calculation.calculate({ payload: random_response }) + + it('should return the expected score', function () { + const EXPECTED_SCORE = 6 + expect(outcome.CHA2DS2_VASC_SCORE).toEqual(EXPECTED_SCORE) + }) + }) + }) +}) diff --git a/src/scores/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.ts b/src/scores/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.ts new file mode 100644 index 0000000..a0b91d9 --- /dev/null +++ b/src/scores/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.ts @@ -0,0 +1,23 @@ +import { + CHA2DS2_VASC_SCORE_INPUTS, + CHA2DS2_VASC_SCORE_OUTPUT, +} from './definition' +import { ScoreType } from '../../types' +import { sum } from 'lodash' + +export const CHA2DS2_VASc_Score: ScoreType< + typeof CHA2DS2_VASC_SCORE_INPUTS, + typeof CHA2DS2_VASC_SCORE_OUTPUT +> = { + name: 'CHA₂DS₂-VASc Score for Atrial Fibrillation Stroke Risk', + readmeLocation: __dirname, + inputSchema: CHA2DS2_VASC_SCORE_INPUTS, + outputSchema: CHA2DS2_VASC_SCORE_OUTPUT, + calculate: ({ data }) => { + const totalScore = sum(Object.values(data)) + + return { + CHA2DS2_VASC_SCORE: totalScore, + } + }, +} diff --git a/todo/CHA2DS2_VASc_Score/README.md b/src/scores/CHA2DS2_VASc_Score/README.md similarity index 100% rename from todo/CHA2DS2_VASc_Score/README.md rename to src/scores/CHA2DS2_VASc_Score/README.md diff --git a/todo/CHA2DS2_VASc_Score/__testdata__/CHA2DS2_VASc_Score_test_responses.ts b/src/scores/CHA2DS2_VASc_Score/__testdata__/CHA2DS2_VASc_Score_test_responses.ts similarity index 100% rename from todo/CHA2DS2_VASc_Score/__testdata__/CHA2DS2_VASc_Score_test_responses.ts rename to src/scores/CHA2DS2_VASc_Score/__testdata__/CHA2DS2_VASc_Score_test_responses.ts diff --git a/todo/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_inputs.ts b/src/scores/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_inputs.ts similarity index 63% rename from todo/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_inputs.ts rename to src/scores/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_inputs.ts index fc53454..9a7246f 100644 --- a/todo/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_inputs.ts +++ b/src/scores/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_inputs.ts @@ -1,12 +1,12 @@ -import type { InputType } from '../../../src/types/calculations.types' +import { z } from 'zod' +import { ScoreInputSchemaType } from '../../../types' -export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ - { - input_id: '1_AGE', +export const CHA2DS2_VASC_SCORE_INPUTS = { + '1_AGE': { label: { en: 'Age' }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2)]), + uiOptions: { + options: [ { label: { en: '<65' }, value: 0, @@ -22,12 +22,11 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, - { - input_id: '2_SEX', + '2_SEX': { label: { en: 'Sex' }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1)]), + uiOptions: { + options: [ { label: { en: 'Male' }, value: 0, @@ -39,12 +38,11 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, - { - input_id: '3_CHF_HISTORY', + '3_CHF_HISTORY': { label: { en: 'CHF history' }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1)]), + uiOptions: { + options: [ { label: { en: 'No' }, value: 0, @@ -56,12 +54,11 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, - { - input_id: '4_HYPERTENSION_HISTORY', + '4_HYPERTENSION_HISTORY': { label: { en: 'Hypertension history' }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1)]), + uiOptions: { + options: [ { label: { en: 'No' }, value: 0, @@ -73,12 +70,11 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, - { - input_id: '5_STROKE_TIA_THROMBOEMBOLISM_HISTORY', + '5_STROKE_TIA_THROMBOEMBOLISM_HISTORY': { label: { en: 'Stroke/TIA/thromboembolism history' }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(2)]), + uiOptions: { + options: [ { label: { en: 'No' }, value: 0, @@ -90,14 +86,13 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, - { - input_id: '6_VASCULAR_DISEASE_HISTORY', + '6_VASCULAR_DISEASE_HISTORY': { label: { en: 'Vascular disease history (prior MI, peripheral artery disease, or aortic plaque)', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1)]), + uiOptions: { + options: [ { label: { en: 'No' }, value: 0, @@ -109,12 +104,11 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, - { - input_id: '7_DIABETES_HISTORY', + '7_DIABETES_HISTORY': { label: { en: 'Diabetes history' }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1)]), + uiOptions: { + options: [ { label: { en: 'No' }, value: 0, @@ -126,4 +120,4 @@ export const CHA2DS2_VASC_SCORE_INPUTS: Array = [ ], }, }, -] +} satisfies ScoreInputSchemaType diff --git a/src/scores/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_output.ts b/src/scores/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_output.ts new file mode 100644 index 0000000..fc1f176 --- /dev/null +++ b/src/scores/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const CHA2DS2_VASC_SCORE_OUTPUT = { + CHA2DS2_VASC_SCORE: { + label: { en: 'CHA₂DS₂-VASc Score' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/CHA2DS2_VASc_Score/definition/index.ts b/src/scores/CHA2DS2_VASc_Score/definition/index.ts similarity index 100% rename from todo/CHA2DS2_VASc_Score/definition/index.ts rename to src/scores/CHA2DS2_VASc_Score/definition/index.ts diff --git a/src/scores/GAD_2/gad_2.test.ts b/src/scores/GAD_2/gad_2.test.ts index 4888690..12b5db0 100644 --- a/src/scores/GAD_2/gad_2.test.ts +++ b/src/scores/GAD_2/gad_2.test.ts @@ -48,7 +48,7 @@ describe('gad_2', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => gad_2_calculation.calculate({ payload: { diff --git a/src/scores/GAD_2/gad_2.ts b/src/scores/GAD_2/gad_2.ts index 5b03c1d..41412e7 100644 --- a/src/scores/GAD_2/gad_2.ts +++ b/src/scores/GAD_2/gad_2.ts @@ -4,7 +4,6 @@ import { GAD2_INTERPRETATION_TABLE, } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' export const gad_2: ScoreType = { name: 'Generalised Anxiety Disorder Assessment (GAD-2)', diff --git a/src/scores/GAD_7/gad_7.test.ts b/src/scores/GAD_7/gad_7.test.ts index f15d387..4725b0b 100644 --- a/src/scores/GAD_7/gad_7.test.ts +++ b/src/scores/GAD_7/gad_7.test.ts @@ -56,7 +56,7 @@ describe('gad_7', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => gad_7_calculation.calculate({ payload: { diff --git a/src/scores/GAD_7/gad_7.ts b/src/scores/GAD_7/gad_7.ts index 847e232..50ee48d 100644 --- a/src/scores/GAD_7/gad_7.ts +++ b/src/scores/GAD_7/gad_7.ts @@ -1,6 +1,6 @@ import { GAD7_INPUTS, GAD7_OUTPUT, GAD7_INTERPRATION_TABLE } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const gad_7: ScoreType = { name: 'Generalised Anxiety Disorder Assessment (GAD-7)', @@ -8,7 +8,7 @@ export const gad_7: ScoreType = { inputSchema: GAD7_INPUTS, outputSchema: GAD7_OUTPUT, calculate: ({ data }) => { - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) return { GAD7_SCORE: totalScore, diff --git a/src/scores/IBD_control/IBD_control.test.ts b/src/scores/IBD_control/IBD_control.test.ts new file mode 100644 index 0000000..1a7fe7e --- /dev/null +++ b/src/scores/IBD_control/IBD_control.test.ts @@ -0,0 +1,174 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + max_response, + median_response, + min_response, + random_response, +} from './__testdata__/IBD_control_responses' +import { IBD_control } from './IBD_control' + +const IBD_CONTROL_8_MIN_SCORE = 0 +const IBD_CONTROL_8_MEDIAN_SCORE = 8 +const IBD_CONTROL_8_MAX_SCORE = 16 + +const IBD_CONTROL_VAS_MIN_SCORE = 0 +const IBD_CONTROL_VAS_MEDIAN_SCORE = 50 +const IBD_CONTROL_VAS_MAX_SCORE = 100 + +const ibd_control_calculation = new Score(IBD_control) + +describe('IBD_control', function () { + it('IBD_control calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('IBD_control') + }) + + describe('the score includes the correct input fields', function () { + it('should use the correct input fields', function () { + const EXPECTED_CALCULATION_INPUT_IDS = [ + 'ibd_control_1a', + 'ibd_control_1b', + 'ibd_control_3a', + 'ibd_control_3b', + 'ibd_control_3c', + 'ibd_control_3d', + 'ibd_control_3e', + 'ibd_control_3f', + 'ibd_control_5', + ] + + const configured_calculation_input_ids = Object.keys( + ibd_control_calculation.inputSchema, + ) + + expect(configured_calculation_input_ids).toEqual( + EXPECTED_CALCULATION_INPUT_IDS, + ) + }) + }) + + describe('each calculated score includes the correct output result and correct score title', function () { + const outcome = ibd_control_calculation.calculate({ payload: min_response }) + + it('should return 2 scores', function () { + expect(Object.keys(outcome).length).toEqual(2) + }) + + it('should have the correct calculation ids', function () { + const EXPECTED_CALCULATION_IDS = ['IBD_CONTROL_8', 'IBD_CONTROL_VAS'] + + const extracted_calculation_ids_from_outcome = Object.keys(outcome) + + expect(EXPECTED_CALCULATION_IDS).toEqual( + extracted_calculation_ids_from_outcome, + ) + }) + }) + + describe('each calculated score includes the correct formula and outputs the correct result', function () { + describe('when a minimum response is passed', function () { + const outcome = ibd_control_calculation.calculate({ + payload: min_response, + }) + + it('should return the minimum score for IBD-Control-8', function () { + expect(outcome.IBD_CONTROL_8).toEqual(IBD_CONTROL_8_MIN_SCORE) + }) + + it('should return the minimum score for IBD-Control-VAS', function () { + expect(outcome.IBD_CONTROL_VAS).toEqual(IBD_CONTROL_VAS_MIN_SCORE) + }) + }) + + describe('when a median response is passed', function () { + const outcome = ibd_control_calculation.calculate({ + payload: median_response, + }) + + it('should return the median score for IBD-Control-8', function () { + expect(outcome.IBD_CONTROL_8).toEqual(IBD_CONTROL_8_MEDIAN_SCORE) + }) + + it('should return the median score for IBD-Control-VAS', function () { + expect(outcome.IBD_CONTROL_VAS).toEqual(IBD_CONTROL_VAS_MEDIAN_SCORE) + }) + }) + + describe('when a maximum response is passed', function () { + const outcome = ibd_control_calculation.calculate({ + payload: max_response, + }) + + it('should return the maximum score for IBD-Control-8', function () { + expect(outcome.IBD_CONTROL_8).toEqual(IBD_CONTROL_8_MAX_SCORE) + }) + + it('should return the maximum score for IBD-Control-VAS', function () { + expect(outcome.IBD_CONTROL_VAS).toEqual(IBD_CONTROL_VAS_MAX_SCORE) + }) + }) + + describe('when a random response is passed', function () { + const outcome = ibd_control_calculation.calculate({ + payload: random_response, + }) + + it('should return the expected score for IBD-Control-8', function () { + const EXPECTED_CONTROL_8_SCORE = 7 + expect(outcome.IBD_CONTROL_8).toEqual(EXPECTED_CONTROL_8_SCORE) + }) + + it('should return the expected score for IBD-Control-VAS', function () { + const EXPECTED_CONTROL_VAS_SCORE = 54 + expect(outcome.IBD_CONTROL_VAS).toEqual(EXPECTED_CONTROL_VAS_SCORE) + }) + }) + }) + + describe('a score is only calculated when all mandatory fields are entered', function () { + describe('when an empty response is passed', function () { + it('should throw a ZodError', function () { + expect(() => + ibd_control_calculation.calculate({ payload: {} }), + ).toThrow(ZodError) + }) + }) + }) + + describe('values entered by the user are checked to verify they are inside specified ranges', function () { + describe('when an answer is not a number', function () { + it('should throw an ZodError', function () { + expect(() => + ibd_control_calculation.calculate({ + payload: { + ibd_control_1a: "I'm not a number", + }, + }), + ).toThrow(ZodError) + }) + }) + describe('when an answer is below the allowed answers', function () { + it('should throw an ZodError', function () { + expect(() => + ibd_control_calculation.calculate({ + payload: { + ibd_control_1a: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + describe('when an answer is above the allowed answers', function () { + it('should throw an ZodError', function () { + expect(() => + ibd_control_calculation.calculate({ + payload: { + ibd_control_5: 101, // VAS + }, + }), + ).toThrow(ZodError) + }) + }) + }) +}) diff --git a/src/scores/IBD_control/IBD_control.ts b/src/scores/IBD_control/IBD_control.ts new file mode 100644 index 0000000..5cbf687 --- /dev/null +++ b/src/scores/IBD_control/IBD_control.ts @@ -0,0 +1,35 @@ +import { IBD_CONTROL_INPUTS, IBD_CONTROL_OUTPUT } from './definition' +import { ScoreType } from '../../types' +import { sum } from 'lodash' + +export const IBD_control: ScoreType< + typeof IBD_CONTROL_INPUTS, + typeof IBD_CONTROL_OUTPUT +> = { + name: 'IBD-Control', + readmeLocation: __dirname, + inputSchema: IBD_CONTROL_INPUTS, + outputSchema: IBD_CONTROL_OUTPUT, + calculate: ({ data }) => { + const recoded_ibd_control_1b = + data.ibd_control_1b === 999 ? 1 : data.ibd_control_1b + + const ibdControlValues = [ + data.ibd_control_1a, + recoded_ibd_control_1b, + data.ibd_control_3a, + data.ibd_control_3b, + data.ibd_control_3c, + data.ibd_control_3d, + data.ibd_control_3e, + data.ibd_control_3f, + ] + + const ibdControl8Score = sum(ibdControlValues) + + return { + IBD_CONTROL_8: ibdControl8Score, + IBD_CONTROL_VAS: data.ibd_control_5, + } + }, +} diff --git a/todo/IBD_control/README.md b/src/scores/IBD_control/README.md similarity index 100% rename from todo/IBD_control/README.md rename to src/scores/IBD_control/README.md diff --git a/todo/IBD_control/__testdata__/IBD_control_responses.ts b/src/scores/IBD_control/__testdata__/IBD_control_responses.ts similarity index 100% rename from todo/IBD_control/__testdata__/IBD_control_responses.ts rename to src/scores/IBD_control/__testdata__/IBD_control_responses.ts diff --git a/todo/IBD_control/definition/ibd_control_inputs.ts b/src/scores/IBD_control/definition/ibd_control_inputs.ts similarity index 70% rename from todo/IBD_control/definition/ibd_control_inputs.ts rename to src/scores/IBD_control/definition/ibd_control_inputs.ts index 8c3245c..44d17dd 100644 --- a/todo/IBD_control/definition/ibd_control_inputs.ts +++ b/src/scores/IBD_control/definition/ibd_control_inputs.ts @@ -1,39 +1,47 @@ -import type { InputType } from '../../../src/types/calculations.types' -import { NumberInputType } from '../../../src/types/calculations/inputs/calculation-inputs.types' +import { z } from 'zod' +import { EnumNumberInputType, ScoreInputSchemaType } from '../../../types' const YES_ANSWER = 1 const NO_ANSWER = 0 const NOT_SURE_ANSWER = 2 export const NO_TREATMENT = 999 -const type: NumberInputType = { - type: 'number', - allowed_answers: [ - { value: NO_ANSWER, label: { en: 'No' } }, - { value: YES_ANSWER, label: { en: 'Yes' } }, - { value: NOT_SURE_ANSWER, label: { en: 'Not sure' } }, - ], -} +const type = { + type: z.union([ + z.literal(NO_ANSWER), + z.literal(YES_ANSWER), + z.literal(NOT_SURE_ANSWER), + ]), + uiOptions: { + options: [ + { value: NO_ANSWER, label: { en: 'No' } }, + { value: YES_ANSWER, label: { en: 'Yes' } }, + { value: NOT_SURE_ANSWER, label: { en: 'Not sure' } }, + ], + }, +} satisfies EnumNumberInputType -export const IBD_CONTROL_INPUTS: Array = [ - { - input_id: 'ibd_control_1a', +export const IBD_CONTROL_INPUTS = { + ibd_control_1a: { label: { nl: 'Gelooft u dat uw darmaandoening goed onder controle is de laatste 2 weken?', en: 'Do you believe that your IBD has been well controlled in the past two weeks?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_1b', + ibd_control_1b: { label: { nl: 'Gelooft u dat uw huidige behandeling nuttig is voor de controle van uw darmklachten?', en: 'Do you believe that your current treatment is useful in controlling IBD?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([ + z.literal(NO_ANSWER), + z.literal(YES_ANSWER), + z.literal(NOT_SURE_ANSWER), + z.literal(NO_TREATMENT), + ]), + uiOptions: { + options: [ { value: NO_ANSWER, label: { en: 'No' } }, { value: YES_ANSWER, label: { en: 'Yes' } }, { value: NOT_SURE_ANSWER, label: { en: 'Not sure' } }, @@ -49,86 +57,69 @@ export const IBD_CONTROL_INPUTS: Array = [ info: { en: `Answer "no_treatment" (999) will be recoded to a value of 1.`, }, - required: true, }, - { - input_id: 'ibd_control_3a', + ibd_control_3a: { label: { nl: 'Hebt u in de laatste 2 weken geplande activiteiten gemist omwille van uw darmaandoening (school/werk/uitstap/…)?', en: 'In the past 2 weeks, did you miss any planned activities because of IBD?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_3b', + ibd_control_3b: { label: { nl: 'Bent u in de laatste 2 weken ’s nachts wakker geworden omwille van uw darmklachten?', en: 'In the past 2 weeks, did you wake up at night because of symptoms of IBD?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_3c', + ibd_control_3c: { label: { nl: 'Hebt u in de laatste 2 weken last gehad van pijn of ongemak?', en: 'In the past 2 weeks, did you suffer from signifcant pain or discomfort?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_3d', + ibd_control_3d: { label: { nl: 'Hebt u in de laatste 2 weken vaak (= meer dan de helft van de tijd) een gebrek aan energie bemerkt (vermoeidheid)?', en: 'In the past 2 weeks, did youoften feel lacking in energy (fatigued)?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_3e', + ibd_control_3e: { label: { nl: 'Hebt u in de laatste 2 weken vaak een angstig of depressief gevoel gehad omwille van uw darmaandoening?', en: 'In the past 2 weeks, did you feel anxious or depressed because of your IBD?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_3f', + ibd_control_3f: { label: { nl: 'Hebt u in de laatste 2 weken gedacht dat uw behandeling dient te worden aangepast?', en: 'In the past 2 weeks, did you think you needed a change to your treatment?', }, - input_type, - required: true, + ...type, }, - { - input_id: 'ibd_control_5', // IBD-Control-VAS input + ibd_control_5: { label: { nl: 'Hoe scoort u de totale controle van uw darmprobleem over de laatste 2 weken? Gelieve een punt op onderstaande lijn te markeren door het bolletje te verschuiven.', en: 'How would you rate your OVERALL control of your IBD in the past two weeks?', }, - type: { - type: 'number', + type: z.number().min(0).max(100), + uiOptions: { component: 'slider', range: { min: { - value: 0, label: { en: 'Worst possible control', nl: 'Slechtst mogelijke controle', }, }, max: { - value: 100, label: { en: 'Best possible control', nl: 'Best mogelijke controle' }, }, }, }, info: { en: 'IBD-Control-VAS' }, - required: true, }, -] +} satisfies ScoreInputSchemaType diff --git a/src/scores/IBD_control/definition/ibd_control_output.ts b/src/scores/IBD_control/definition/ibd_control_output.ts new file mode 100644 index 0000000..e1b6014 --- /dev/null +++ b/src/scores/IBD_control/definition/ibd_control_output.ts @@ -0,0 +1,13 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const IBD_CONTROL_OUTPUT = { + IBD_CONTROL_8: { + label: { en: 'IBD-Control-8 Score' }, + type: z.number(), + }, + IBD_CONTROL_VAS: { + label: { en: 'IBD-Control-VAS Score' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/IBD_control/definition/index.ts b/src/scores/IBD_control/definition/index.ts similarity index 100% rename from todo/IBD_control/definition/index.ts rename to src/scores/IBD_control/definition/index.ts diff --git a/src/scores/acro/acro.test.ts b/src/scores/acro/acro.test.ts index 4064d77..58f3711 100644 --- a/src/scores/acro/acro.test.ts +++ b/src/scores/acro/acro.test.ts @@ -123,7 +123,7 @@ describe('acro', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => acro_calculation.calculate({ payload: { @@ -135,7 +135,7 @@ describe('acro', function () { }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => acro_calculation.calculate({ payload: { @@ -147,7 +147,7 @@ describe('acro', function () { }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => acro_calculation.calculate({ payload: { diff --git a/src/scores/acro/helpers/calculate_scores.ts b/src/scores/acro/helpers/calculate_scores.ts index 8a146b4..313fafc 100644 --- a/src/scores/acro/helpers/calculate_scores.ts +++ b/src/scores/acro/helpers/calculate_scores.ts @@ -1,24 +1,22 @@ -import R from 'ramda' - import { ACRO_SUBSCALES, type SubscaleType } from '../definition/acro_subscales' import { z } from 'zod' -import _ from 'lodash' +import { sum, compact, filter } from 'lodash' import { ACRO_INPUTS } from '../definition' export const calculate_scores = ( inputs_with_answers: z.infer< z.ZodObject<{ - [K in keyof typeof ACRO_INPUTS]: typeof ACRO_INPUTS[K]['type'] + [K in keyof typeof ACRO_INPUTS]: (typeof ACRO_INPUTS)[K]['type'] }> >, - subscale: SubscaleType + subscale: SubscaleType, ): number | null => { const INPUT_IDS_NEEDED_FOR_SCORING = ACRO_SUBSCALES[subscale] - const valid_answers_in_subscale = _.compact( - _.filter(inputs_with_answers, (_i, key) => - INPUT_IDS_NEEDED_FOR_SCORING.includes(key) - ) + const valid_answers_in_subscale = compact( + filter(inputs_with_answers, (_i, key) => + INPUT_IDS_NEEDED_FOR_SCORING.includes(key), + ), ) if ( @@ -27,7 +25,7 @@ export const calculate_scores = ( return null } - const subscaleTotal = R.sum(valid_answers_in_subscale) + const subscaleTotal = sum(valid_answers_in_subscale) const bestScores = { PHYSICAL_SUBSCALE: 40, diff --git a/src/scores/age_calc/age_calc.test.ts b/src/scores/age_calc/age_calc.test.ts index bd01a69..12de2a0 100644 --- a/src/scores/age_calc/age_calc.test.ts +++ b/src/scores/age_calc/age_calc.test.ts @@ -1,9 +1,7 @@ -import moment from 'moment' - import { ScoreLibrary } from '../library' import { age_calc } from './age_calc' import { Score } from '../../classes' - +import MockDate from 'mockdate' const calculate_age = new Score(age_calc) describe('age_calc', function () { @@ -45,13 +43,13 @@ describe('age_calc', function () { describe('each calculated score shall include the correct formula and output the correct result', function () { it('should return correct result age', function () { const dob = '1993-11-30' + MockDate.set('2025-01-01T00:00:00Z') + const EXPECTED_AGE = 31 const result = calculate_age.calculate({ payload: { date_of_birth: '1993-11-30' }, }) - const EXPECTED_AGE = moment().diff(dob, 'years') - expect(result.AGE).toEqual(EXPECTED_AGE) }) }) diff --git a/src/scores/age_calc/age_calc.ts b/src/scores/age_calc/age_calc.ts index 4314f08..c9fe862 100644 --- a/src/scores/age_calc/age_calc.ts +++ b/src/scores/age_calc/age_calc.ts @@ -1,4 +1,3 @@ -import moment from 'moment' import { ScoreType } from '../../types' import { AGE_CALC_OUTPUT, AGE_CALC_INPUTS } from './definition' @@ -11,11 +10,19 @@ export const age_calc: ScoreType< inputSchema: AGE_CALC_INPUTS, outputSchema: AGE_CALC_OUTPUT, calculate: ({ data }) => { - const dobMoment = moment(data.date_of_birth, moment.ISO_8601) - const age = moment().diff(dobMoment, 'years') + const dateOfBirth = new Date(data.date_of_birth) + const today = new Date() + + const age = today.getFullYear() - dateOfBirth.getFullYear() + const isBirthdayPassed = + today.getMonth() > dateOfBirth.getMonth() || + (today.getMonth() === dateOfBirth.getMonth() && + today.getDate() >= dateOfBirth.getDate()) + + const adjustedAge = isBirthdayPassed ? age : age - 1 return { - AGE: age, + AGE: adjustedAge, } }, } diff --git a/src/scores/asrs/asrs.test.ts b/src/scores/asrs/asrs.test.ts index dc60371..f97d1a0 100644 --- a/src/scores/asrs/asrs.test.ts +++ b/src/scores/asrs/asrs.test.ts @@ -140,7 +140,7 @@ describe('asrs', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => asrs_calculation.calculate({ payload: { @@ -152,7 +152,7 @@ describe('asrs', function () { }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => asrs_calculation.calculate({ payload: { @@ -164,7 +164,7 @@ describe('asrs', function () { }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => asrs_calculation.calculate({ payload: { diff --git a/src/scores/asrs/helpers/calculate_part_scores.ts b/src/scores/asrs/helpers/calculate_part_scores.ts index d62d9e1..7c15875 100644 --- a/src/scores/asrs/helpers/calculate_part_scores.ts +++ b/src/scores/asrs/helpers/calculate_part_scores.ts @@ -1,8 +1,6 @@ -import R from 'ramda' - import { ASRS_PARTS, type PartType } from '../definition/asrs_parts' import { ASRS_INPUTS, POSITIVE_SCORES } from '../definition' -import _ from 'lodash' +import { sum, map, pick } from 'lodash' import { z } from 'zod' export const calculate_part_scores = ( @@ -15,11 +13,8 @@ export const calculate_part_scores = ( ): number | null => { const INPUT_IDS_NEEDED_FOR_SCORING = ASRS_PARTS[part] - const inputs_in_part = _.pick( - inputs_with_answers, - INPUT_IDS_NEEDED_FOR_SCORING, - ) - const standardized_input_scores = _.map(inputs_in_part, (_i, key: string) => { + const inputs_in_part = pick(inputs_with_answers, INPUT_IDS_NEEDED_FOR_SCORING) + const standardized_input_scores = map(inputs_in_part, (_i, key: string) => { const positive_scores = POSITIVE_SCORES[key as keyof typeof POSITIVE_SCORES] if (positive_scores === undefined || _i === undefined) return null @@ -31,5 +26,5 @@ export const calculate_part_scores = ( if (standardized_input_scores.length === 0) return null - return R.sum(standardized_input_scores as number[]) + return sum(standardized_input_scores as number[]) } diff --git a/src/scores/asrs/helpers/calculate_subscale_scores.ts b/src/scores/asrs/helpers/calculate_subscale_scores.ts index 340649e..7998f5c 100644 --- a/src/scores/asrs/helpers/calculate_subscale_scores.ts +++ b/src/scores/asrs/helpers/calculate_subscale_scores.ts @@ -1,9 +1,7 @@ -import R from 'ramda' - import { ASRS_SUBSCALES, type SubscaleType } from '../definition/asrs_subscales' import { ASRS_INPUTS, POSITIVE_SCORES } from '../definition' import { z } from 'zod' -import _ from 'lodash' +import { sum, map, pick } from 'lodash' export const calculate_subscale_scores = ( inputs_with_answers: z.infer< @@ -15,12 +13,12 @@ export const calculate_subscale_scores = ( ): number | null => { const INPUT_IDS_NEEDED_FOR_SCORING = ASRS_SUBSCALES[subscale] - const inputs_in_subscale = _.pick( + const inputs_in_subscale = pick( inputs_with_answers, INPUT_IDS_NEEDED_FOR_SCORING, ) - const standardized_input_scores = _.map(inputs_in_subscale, (_i, key) => { + const standardized_input_scores = map(inputs_in_subscale, (_i, key) => { const positive_scores = POSITIVE_SCORES[key as keyof typeof POSITIVE_SCORES] if (positive_scores === undefined || _i === undefined) return null @@ -32,5 +30,5 @@ export const calculate_subscale_scores = ( if (standardized_input_scores.length === 0) return null - return R.sum(standardized_input_scores as number[]) + return sum(standardized_input_scores as number[]) } diff --git a/src/scores/beck/beck.test.ts b/src/scores/beck/beck.test.ts index d68c266..d9f8ec0 100644 --- a/src/scores/beck/beck.test.ts +++ b/src/scores/beck/beck.test.ts @@ -72,7 +72,7 @@ describe('beck', function () { describe('when called with a response with answers out of the expected [0,3] range', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => beck_calculation.calculate({ payload: { @@ -83,7 +83,7 @@ describe('beck', function () { }) }) describe('when an answer is below the expected [0,3] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => beck_calculation.calculate({ payload: { @@ -95,7 +95,7 @@ describe('beck', function () { }) describe('when an answer is above the expected [0,3] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => beck_calculation.calculate({ payload: { diff --git a/src/scores/beck/beck.ts b/src/scores/beck/beck.ts index 9d33c02..865969f 100644 --- a/src/scores/beck/beck.ts +++ b/src/scores/beck/beck.ts @@ -1,6 +1,6 @@ import { ScoreType } from '../../types' import { BECK_OUTPUT, BECK_INPUTS } from './definition' -import _ from 'lodash' +import { sum, mapValues } from 'lodash' /** * The answer values of question 16 and 18 have to be standardized @@ -20,7 +20,7 @@ const preprocess_beck_response = ( ): Record => { const QUESTIONS_TO_PREPROCESS = ['Q16', 'Q18'] - return _.mapValues(beck_inputs_with_answers, (val, key) => { + return mapValues(beck_inputs_with_answers, (val, key) => { if (QUESTIONS_TO_PREPROCESS.includes(key)) { const value_in_dict = RAW_ANSWER_TO_VALUE_DICT[String(val)] return value_in_dict @@ -37,7 +37,7 @@ export const beck: ScoreType = { outputSchema: BECK_OUTPUT, calculate: ({ data }) => { const preprocessed_data = preprocess_beck_response(data) - const score = _.sum(Object.values(preprocessed_data)) + const score = sum(Object.values(preprocessed_data)) return { beck: score, diff --git a/src/scores/blcs/blcs.test.ts b/src/scores/blcs/blcs.test.ts index 18032c3..30e69d7 100644 --- a/src/scores/blcs/blcs.test.ts +++ b/src/scores/blcs/blcs.test.ts @@ -43,7 +43,7 @@ describe('blcs', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => blcs_calculation.calculate({ payload: { @@ -55,7 +55,7 @@ describe('blcs', function () { }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => blcs_calculation.calculate({ payload: { @@ -67,7 +67,7 @@ describe('blcs', function () { }) describe('when an answer is above the expected range for Q04', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => blcs_calculation.calculate({ payload: { @@ -79,7 +79,7 @@ describe('blcs', function () { }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => blcs_calculation.calculate({ payload: { diff --git a/src/scores/blcs/blcs.ts b/src/scores/blcs/blcs.ts index a1937a8..29338da 100644 --- a/src/scores/blcs/blcs.ts +++ b/src/scores/blcs/blcs.ts @@ -1,4 +1,4 @@ -import _ from 'lodash' +import { sum } from 'lodash' import { BLCS_INPUTS, BLCS_OUTPUT } from './definition' import { ScoreType } from '../../types' @@ -13,7 +13,7 @@ export const blcs: ScoreType = { if (valid_answers.length === 0) return { BLCS_TOTAL_SCORE: null } return { - BLCS_TOTAL_SCORE: _.sum(valid_answers), + BLCS_TOTAL_SCORE: sum(valid_answers), } }, } diff --git a/src/scores/bmi/us/bmi.test.ts b/src/scores/bmi/us/bmi.test.ts index 88986cf..efd09f7 100644 --- a/src/scores/bmi/us/bmi.test.ts +++ b/src/scores/bmi/us/bmi.test.ts @@ -74,7 +74,7 @@ describe('bmi_imperial', function () { ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when "weight" is not in the expected range', function () { + it('should throw an ZodError when "weight" is not in the expected range', function () { expect(() => calculation.calculate({ payload: { @@ -86,7 +86,7 @@ describe('bmi_imperial', function () { ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when "height" is not in the expected range', function () { + it('should throw an ZodError when "height" is not in the expected range', function () { expect(() => calculation.calculate({ payload: { diff --git a/src/scores/bmi/us/bmi.ts b/src/scores/bmi/us/bmi.ts index 17cb48a..6ec4739 100644 --- a/src/scores/bmi/us/bmi.ts +++ b/src/scores/bmi/us/bmi.ts @@ -1,5 +1,5 @@ import { BmiOutputSchema, BmiInputSchema } from './bmi.schema' -import { round } from 'mathjs' +import { round } from 'lodash' import { ScoreType } from '../../../types' export const bmi_us: ScoreType = diff --git a/src/scores/bwcs/bwcs.test.ts b/src/scores/bwcs/bwcs.test.ts index 2b89ae0..cde8fe8 100644 --- a/src/scores/bwcs/bwcs.test.ts +++ b/src/scores/bwcs/bwcs.test.ts @@ -43,7 +43,7 @@ describe('bwcs', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => bwcs_calculation.calculate({ payload: { @@ -55,7 +55,7 @@ describe('bwcs', function () { }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => bwcs_calculation.calculate({ payload: { @@ -67,7 +67,7 @@ describe('bwcs', function () { }) describe('when an answer is above the expected range for Q04', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => bwcs_calculation.calculate({ payload: { @@ -79,7 +79,7 @@ describe('bwcs', function () { }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => bwcs_calculation.calculate({ payload: { diff --git a/src/scores/bwcs/bwcs.ts b/src/scores/bwcs/bwcs.ts index 741f512..95bf5fb 100644 --- a/src/scores/bwcs/bwcs.ts +++ b/src/scores/bwcs/bwcs.ts @@ -1,4 +1,4 @@ -import _ from 'lodash' +import { sum } from 'lodash' import { BWCS_INPUTS, BWCS_OUTPUT } from './definition' import { ScoreType } from '../../types' @@ -13,7 +13,7 @@ export const bwcs: ScoreType = { if (valid_answers.length === 0) return { BWCS_TOTAL_SCORE: null } return { - BWCS_TOTAL_SCORE: _.sum(valid_answers), + BWCS_TOTAL_SCORE: sum(valid_answers), } }, } diff --git a/todo/caregiver_strain_index/README.md b/src/scores/caregiver_strain_index/README.md similarity index 100% rename from todo/caregiver_strain_index/README.md rename to src/scores/caregiver_strain_index/README.md diff --git a/todo/caregiver_strain_index/__testdata__/caregiver_strain_index_test_responses.ts b/src/scores/caregiver_strain_index/__testdata__/caregiver_strain_index_test_responses.ts similarity index 100% rename from todo/caregiver_strain_index/__testdata__/caregiver_strain_index_test_responses.ts rename to src/scores/caregiver_strain_index/__testdata__/caregiver_strain_index_test_responses.ts diff --git a/src/scores/caregiver_strain_index/caregiver_strain_index.test.ts b/src/scores/caregiver_strain_index/caregiver_strain_index.test.ts new file mode 100644 index 0000000..5ec51dc --- /dev/null +++ b/src/scores/caregiver_strain_index/caregiver_strain_index.test.ts @@ -0,0 +1,162 @@ +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + max_response, + median_response, + min_response, + random_response, +} from './__testdata__/caregiver_strain_index_test_responses' +import { caregiver_strain_index } from './caregiver_strain_index' +import { ZodError } from 'zod' + +const CSI_MIN_SCORE = 0 +const CSI_MEDIAN_SCORE = 6 // or 7 but test is written for 6 +const CSI_MAX_SCORE = 13 + +const caregiver_strain_index_calculation = new Score(caregiver_strain_index) + +describe('caregiver_strain_index', function () { + it('caregiver_strain_index calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('caregiver_strain_index') + }) + + describe('basic assumption', function () { + describe('the score includes the correct input fields', function () { + it('should use the correct input fields', function () { + const EXPECTED_CALCULATION_INPUT_IDS = [ + 'CSI_Q01', + 'CSI_Q02', + 'CSI_Q03', + 'CSI_Q04', + 'CSI_Q05', + 'CSI_Q06', + 'CSI_Q07', + 'CSI_Q08', + 'CSI_Q09', + 'CSI_Q10', + 'CSI_Q11', + 'CSI_Q12', + 'CSI_Q13', + ] + + const CONFIGURED_CALCULATION_INPUT_IDS = Object.keys( + caregiver_strain_index_calculation.inputSchema, + ) + + expect(EXPECTED_CALCULATION_INPUT_IDS).toEqual( + CONFIGURED_CALCULATION_INPUT_IDS, + ) + }) + }) + + describe('each calculated score includes the correct output result and correct score title', function () { + const outcome = caregiver_strain_index_calculation.calculate({ + payload: min_response, + }) + + it('should calculate a single score', function () { + expect(Object.keys(outcome).length).toEqual(1) + }) + + it('should have the correct calculation id', function () { + const EXPECTED_CALCULATION_ID = ['CAREGIVER_STRAIN_INDEX'] + const configured_calculation_id = Object.keys(outcome) + + expect(configured_calculation_id).toEqual(EXPECTED_CALCULATION_ID) + }) + }) + }) + + describe('score calculations', function () { + describe('each calculated score includes the correct formula and outputs the correct result', function () { + describe('when a minimum response is passed', function () { + it('should return the minimum score', function () { + const score = caregiver_strain_index_calculation.calculate({ + payload: min_response, + }) + + expect(score.CAREGIVER_STRAIN_INDEX).toEqual(CSI_MIN_SCORE) + }) + }) + + describe('when a median response is passed', function () { + it('should return the median score', function () { + const score = caregiver_strain_index_calculation.calculate({ + payload: median_response, + }) + + expect(score.CAREGIVER_STRAIN_INDEX).toEqual(CSI_MEDIAN_SCORE) + }) + }) + + describe('when a maximum response is passed', function () { + it('should return the maximum score', function () { + const score = caregiver_strain_index_calculation.calculate({ + payload: max_response, + }) + + expect(score.CAREGIVER_STRAIN_INDEX).toEqual(CSI_MAX_SCORE) + }) + }) + + describe('when a random response is passed', function () { + it('should return the expected score', function () { + const score = caregiver_strain_index_calculation.calculate({ + payload: random_response, + }) + + const EXPECTED_SCORE = 7 + expect(score.CAREGIVER_STRAIN_INDEX).toEqual(EXPECTED_SCORE) + }) + }) + }) + }) + + describe('validations', function () { + describe('a score is only calculated when all mandatory fields are entered', function () { + describe('when an empty response is passed', function () { + it('should throw a ZodError', function () { + expect(() => + caregiver_strain_index_calculation.calculate({ payload: {} }), + ).toThrow(ZodError) + }) + }) + }) + + describe('values entered by the user are checked to verify they are inside specified ranges', function () { + describe('when an answer is not a number', function () { + it('should throw an ZodError', function () { + expect(() => + caregiver_strain_index_calculation.calculate({ + payload: { + CSI_Q01: "I'm not a number", + }, + }), + ).toThrow(ZodError) + }) + }) + describe('when an answer is below 0 (i.e. not 0 = no or 1 = yes)', function () { + it('should throw an ZodError', function () { + expect(() => + caregiver_strain_index_calculation.calculate({ + payload: { + CSI_Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + describe('when an answer is above 1 (i.e. not 0 = no or 1 = yes)', function () { + it('should throw an ZodError', function () { + expect(() => + caregiver_strain_index_calculation.calculate({ + payload: { + CSI_Q01: 2, + }, + }), + ).toThrow(ZodError) + }) + }) + }) + }) +}) diff --git a/src/scores/caregiver_strain_index/caregiver_strain_index.ts b/src/scores/caregiver_strain_index/caregiver_strain_index.ts new file mode 100644 index 0000000..09c201e --- /dev/null +++ b/src/scores/caregiver_strain_index/caregiver_strain_index.ts @@ -0,0 +1,23 @@ +import { + CAREGIVER_STRAIN_INDEX_INPUTS, + CAREGIVER_STRAIN_INDEX_OUTPUT, +} from './definition' +import { ScoreType } from '../../types' +import { sum } from 'lodash' + +export const caregiver_strain_index: ScoreType< + typeof CAREGIVER_STRAIN_INDEX_INPUTS, + typeof CAREGIVER_STRAIN_INDEX_OUTPUT +> = { + name: 'Caregiver Strain Index (CSI)', + readmeLocation: __dirname, + inputSchema: CAREGIVER_STRAIN_INDEX_INPUTS, + outputSchema: CAREGIVER_STRAIN_INDEX_OUTPUT, + calculate: ({ data }) => { + const totalScore = sum(Object.values(data)) + + return { + CAREGIVER_STRAIN_INDEX: totalScore, + } + }, +} diff --git a/todo/caregiver_strain_index/definition/caregiver_strain_index_inputs.ts b/src/scores/caregiver_strain_index/definition/caregiver_strain_index_inputs.ts similarity index 67% rename from todo/caregiver_strain_index/definition/caregiver_strain_index_inputs.ts rename to src/scores/caregiver_strain_index/definition/caregiver_strain_index_inputs.ts index 8d591f1..004f52f 100644 --- a/todo/caregiver_strain_index/definition/caregiver_strain_index_inputs.ts +++ b/src/scores/caregiver_strain_index/definition/caregiver_strain_index_inputs.ts @@ -1,133 +1,109 @@ -import type { InputType } from '../../../src/types/calculations.types' -import { NumberInputType } from '../../../src/types/calculations/inputs/calculation-inputs.types' +import { z } from 'zod' +import { EnumNumberInputType } from '../../../types' const NO_ANSWER = 0 const YES_ANSWER = 1 -const type: NumberInputType = { - type: 'number', - allowed_answers: [ - { value: NO_ANSWER, label: { en: 'No', nl: 'Nee' } }, - { value: YES_ANSWER, label: { en: 'Yes', nl: 'Ja' } }, - ], -} +const type = { + type: z.union([z.literal(NO_ANSWER), z.literal(YES_ANSWER)]), + uiOptions: { + options: [ + { value: NO_ANSWER, label: { en: 'No', nl: 'Nee' } }, + { value: YES_ANSWER, label: { en: 'Yes', nl: 'Ja' } }, + ], + }, +} satisfies EnumNumberInputType -export const CAREGIVER_STRAIN_INDEX_INPUTS: Array = [ - { - input_id: 'CSI_Q01', +export const CAREGIVER_STRAIN_INDEX_INPUTS = { + CSI_Q01: { label: { nl: 'Mijn nachtrust is verstoord.', en: 'My sleep is disturbed (e.g., because the person I care for is in and out of bed or wanders around at night)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q02', + CSI_Q02: { label: { nl: 'Hem of haar helpen kost me nogal wat moeite en tijd.', en: 'Caregiving is inconvenient (e.g., helping takes so much time or it’s a long drive over to help)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q03', + CSI_Q03: { label: { nl: 'Ik vind het lichamelijk zwaar.', en: 'It is a physical strain (e.g., because of lifting in and out of a chair; effort or concentration is required)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q04', + CSI_Q04: { label: { nl: 'Het beperkt me in andere dingen die ik wil doen.', en: 'Caregiving is confining (e.g., helping restricts free time or cannot go visiting)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q05', + CSI_Q05: { label: { nl: 'Wij hebben onze dagelijkse manier van doen moeten aanpassen.', en: 'There have been family adjustments (e.g., because helping has disrupted routine; there has been no privacy)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q06', + CSI_Q06: { label: { nl: 'Wij hebben onze plannen moeten wijzigen.', en: 'There have been changes in personal plans (e.g., had to turn down a job; could not go on vacation)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q07', + CSI_Q07: { label: { nl: 'Er zijn ook andere zaken waaraan ik mijn tijd moet besteden.', en: 'There have been other demands on my time (e.g., other family members need me)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q08', + CSI_Q08: { label: { nl: 'Emotioneel gedragen we ons anders ten opzichte van elkaar.', en: 'There have been emotional adjustments (e.g., because of severe arguments)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q09', + CSI_Q09: { label: { nl: 'Het gedrag van mijn man/vrouw maakt me soms van streek.', en: 'Some behavior is upsetting (e.g., because of incontinence; the person I care for has trouble remembering things; or the person I care for accuses people of taking things)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q10', + CSI_Q10: { label: { nl: 'Het is pijnlijk te moeten zien dat hij/zij een ander persoon is geworden.', en: 'It is upsetting to find that he/she has changed so much from his/her former self (e.g., he/she is a different person than he/she used to be)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q11', + CSI_Q11: { label: { nl: 'Ik heb mijn werk/baan moeten aanpassen aan de situatie.', en: 'There have been work adjustments (e.g., because of having to take time off)', }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q12', + CSI_Q12: { label: { nl: 'Ik word geheel door deze situatie in beslag genomen.', en: "I'm feeling completely overwhelmed (e.g., because of worry about the person I care for; concerns about how you I will manage)", }, - input_type, - required: true, + ...type, }, - { - input_id: 'CSI_Q13', + CSI_Q13: { label: { nl: 'We leven onder financiële druk.', en: 'It is a financial strain', }, - input_type, - required: true, + ...type, }, -] +} diff --git a/src/scores/caregiver_strain_index/definition/caregiver_strain_index_output.ts b/src/scores/caregiver_strain_index/definition/caregiver_strain_index_output.ts new file mode 100644 index 0000000..8463fa3 --- /dev/null +++ b/src/scores/caregiver_strain_index/definition/caregiver_strain_index_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const CAREGIVER_STRAIN_INDEX_OUTPUT = { + CAREGIVER_STRAIN_INDEX: { + label: { en: 'CSI score' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/caregiver_strain_index/definition/index.ts b/src/scores/caregiver_strain_index/definition/index.ts similarity index 100% rename from todo/caregiver_strain_index/definition/index.ts rename to src/scores/caregiver_strain_index/definition/index.ts diff --git a/todo/core_om/README.md b/src/scores/core_om/README.md similarity index 100% rename from todo/core_om/README.md rename to src/scores/core_om/README.md diff --git a/todo/core_om/__testdata__/core_om_responses.ts b/src/scores/core_om/__testdata__/core_om_responses.ts similarity index 100% rename from todo/core_om/__testdata__/core_om_responses.ts rename to src/scores/core_om/__testdata__/core_om_responses.ts diff --git a/src/scores/core_om/core_om.test.ts b/src/scores/core_om/core_om.test.ts new file mode 100644 index 0000000..442b0dc --- /dev/null +++ b/src/scores/core_om/core_om.test.ts @@ -0,0 +1,423 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + best_response, + median_response, + random_response, + worst_response, +} from './__testdata__/core_om_responses' +import { core_om } from './core_om' + +const core_om_calculation = new Score(core_om) + +describe('core_om', function () { + it('core_om calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('core_om') + }) + + describe('the score includes the correct input fields', function () { + it('should use the correct input fields', function () { + const EXPECTED_CALCULATION_INPUT_IDS = [ + 'CORE_OM_Q01', + 'CORE_OM_Q02', + 'CORE_OM_Q03', + 'CORE_OM_Q04', + 'CORE_OM_Q05', + 'CORE_OM_Q06', + 'CORE_OM_Q07', + 'CORE_OM_Q08', + 'CORE_OM_Q09', + 'CORE_OM_Q10', + 'CORE_OM_Q11', + 'CORE_OM_Q12', + 'CORE_OM_Q13', + 'CORE_OM_Q14', + 'CORE_OM_Q15', + 'CORE_OM_Q16', + 'CORE_OM_Q17', + 'CORE_OM_Q18', + 'CORE_OM_Q19', + 'CORE_OM_Q20', + 'CORE_OM_Q21', + 'CORE_OM_Q22', + 'CORE_OM_Q23', + 'CORE_OM_Q24', + 'CORE_OM_Q25', + 'CORE_OM_Q26', + 'CORE_OM_Q27', + 'CORE_OM_Q28', + 'CORE_OM_Q29', + 'CORE_OM_Q30', + 'CORE_OM_Q31', + 'CORE_OM_Q32', + 'CORE_OM_Q33', + 'CORE_OM_Q34', + ] + + const configured_calculation_input_ids = Object.keys( + core_om_calculation.inputSchema, + ) + + expect(configured_calculation_input_ids).toEqual( + EXPECTED_CALCULATION_INPUT_IDS, + ) + }) + }) + + describe('each calculated score includes the correct output result and correct score title', function () { + const outcome = core_om_calculation.calculate({ payload: best_response }) + + it('should calculate 4 scoreS', function () { + expect(Object.keys(outcome).length).toEqual(10) + }) + + it('should have the correct calculation ids', function () { + const configured_calculation_id = Object.keys(outcome) + + expect(configured_calculation_id).toEqual([ + 'SUBJECTIVE_WELL_BEING_DEFICITS_RAW', + 'SUBJECTIVE_WELL_BEING_DEFICITS_MEAN', + 'PROBLEMS_SYMPTOMS_RAW', + 'PROBLEMS_SYMPTOMS_MEAN', + 'LIFE_FUNCTIONING_DIFFICULTIES_RAW', + 'LIFE_FUNCTIONING_DIFFICULTIES_MEAN', + 'RISK_HARM_RAW', + 'RISK_HARM_MEAN', + 'TOTAL_RAW', + 'TOTAL_MEAN', + ]) + }) + }) + + describe('each calculated score includes the correct formula and outputs the correct result', function () { + describe('when the best response is passed', function () { + const outcome = core_om_calculation.calculate({ payload: best_response }) + const BEST_SCORE = 0 + + it('should return the best raw score for Subjective well-being deficits', function () { + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_RAW).toEqual(BEST_SCORE) + }) + + it('should return the best mean score for Subjective well-being deficits', function () { + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_MEAN).toEqual(BEST_SCORE) + }) + + it('should return the best raw for Problems/symptoms', function () { + expect(outcome.PROBLEMS_SYMPTOMS_RAW).toEqual(BEST_SCORE) + }) + + it('should return the best mean score for Problems/symptoms', function () { + expect(outcome.PROBLEMS_SYMPTOMS_MEAN).toEqual(BEST_SCORE) + }) + + it('should return the best raw score for Life functioning difficulties', function () { + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_RAW).toEqual(BEST_SCORE) + }) + + it('should return the best mean score for Life functioning difficulties', function () { + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_MEAN).toEqual(BEST_SCORE) + }) + + it('should return the best raw score for Risk/harm', function () { + expect(outcome.RISK_HARM_RAW).toEqual(BEST_SCORE) + }) + + it('should return the best mean score for Risk/harm', function () { + expect(outcome.RISK_HARM_MEAN).toEqual(BEST_SCORE) + }) + + it('should return the best raw score for Total', function () { + expect(outcome.TOTAL_RAW).toEqual(BEST_SCORE) + }) + + it('should return the best mean score for Total', function () { + expect(outcome.TOTAL_MEAN).toEqual(BEST_SCORE) + }) + }) + + describe('when a median response is passed', function () { + const outcome = core_om_calculation.calculate({ + payload: median_response, + }) + const MEDIAN_MEAN_SCORE = 2 + + it('should return the median raw score for Subjective well-being deficits', function () { + const MEDIAN_RAW_SCORE = 8 + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_RAW).toEqual( + MEDIAN_RAW_SCORE, + ) + }) + + it('should return the median mean score for Subjective well-being deficits', function () { + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_MEAN).toEqual( + MEDIAN_MEAN_SCORE, + ) + }) + + it('should return the median raw for Problems/symptoms', function () { + const MEDIAN_RAW_SCORE = 24 + expect(outcome.PROBLEMS_SYMPTOMS_RAW).toEqual(MEDIAN_RAW_SCORE) + }) + + it('should return the median mean score for Problems/symptoms', function () { + expect(outcome.PROBLEMS_SYMPTOMS_MEAN).toEqual(MEDIAN_MEAN_SCORE) + }) + + it('should return the median raw score for Life functioning difficulties', function () { + const MEDIAN_RAW_SCORE = 24 + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_RAW).toEqual( + MEDIAN_RAW_SCORE, + ) + }) + + it('should return the median mean score for Life functioning difficulties', function () { + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_MEAN).toEqual( + MEDIAN_MEAN_SCORE, + ) + }) + + it('should return the median raw score for Risk/harm', function () { + const MEDIAN_RAW_SCORE = 12 + expect(outcome.RISK_HARM_RAW).toEqual(MEDIAN_RAW_SCORE) + }) + + it('should return the median mean score for Risk/harm', function () { + expect(outcome.RISK_HARM_MEAN).toEqual(MEDIAN_MEAN_SCORE) + }) + + it('should return the median raw score for Total', function () { + const MEDIAN_RAW_SCORE = 68 + expect(outcome.TOTAL_RAW).toEqual(MEDIAN_RAW_SCORE) + }) + + it('should return the median mean score for Total', function () { + expect(outcome.TOTAL_MEAN).toEqual(MEDIAN_MEAN_SCORE) + }) + }) + + describe('when the worst response is passed', function () { + const outcome = core_om_calculation.calculate({ payload: worst_response }) + const WORST_MEAN_SCORE = 4 + + it('should return the worst raw score for Subjective well-being deficits', function () { + const WORST_RAW_SCORE = 16 + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_RAW).toEqual( + WORST_RAW_SCORE, + ) + }) + + it('should return the worst mean score for Subjective well-being deficits', function () { + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_MEAN).toEqual( + WORST_MEAN_SCORE, + ) + }) + + it('should return the worst raw score for Problems/symptoms', function () { + const WORST_RAW_SCORE = 48 + expect(outcome.PROBLEMS_SYMPTOMS_RAW).toEqual(WORST_RAW_SCORE) + }) + + it('should return the worst mean score for Problems/symptoms', function () { + expect(outcome.PROBLEMS_SYMPTOMS_MEAN).toEqual(WORST_MEAN_SCORE) + }) + + it('should return the worst raw score for Life functioning difficulties', function () { + const WORST_RAW_SCORE = 48 + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_RAW).toEqual( + WORST_RAW_SCORE, + ) + }) + + it('should return the worst mean score for Life functioning difficulties', function () { + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_MEAN).toEqual( + WORST_MEAN_SCORE, + ) + }) + + it('should return the worst raw score for Risk/harm', function () { + const WORST_RAW_SCORE = 24 + expect(outcome.RISK_HARM_RAW).toEqual(WORST_RAW_SCORE) + }) + + it('should return the worst mean score for Risk/harm', function () { + expect(outcome.RISK_HARM_MEAN).toEqual(WORST_MEAN_SCORE) + }) + + it('should return the worst raw score for Total', function () { + const WORST_RAW_SCORE = 136 + expect(outcome.TOTAL_RAW).toEqual(WORST_RAW_SCORE) + }) + + it('should return the worst mean score for Total', function () { + expect(outcome.TOTAL_MEAN).toEqual(WORST_MEAN_SCORE) + }) + }) + + describe('when a random response is passed', function () { + const outcome = core_om_calculation.calculate({ + payload: random_response, + }) + + it('should return the expected raw score for Subjective well-being deficits', function () { + const EXPECTED_RAW_SCORE = 2 + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_RAW).toEqual( + EXPECTED_RAW_SCORE, + ) + }) + + it('should return the expected mean score for Subjective well-being deficits', function () { + const EXPECTED_MEAN_SCORE = 0.5 + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_MEAN).toEqual( + EXPECTED_MEAN_SCORE, + ) + }) + + it('should return the expected raw for Problems/symptoms', function () { + const EXPECTED_RAW_SCORE = 3 + expect(outcome.PROBLEMS_SYMPTOMS_RAW).toEqual(EXPECTED_RAW_SCORE) + }) + + it('should return the expected mean score for Problems/symptoms', function () { + const EXPECTED_MEAN_SCORE = 0.25 + expect(outcome.PROBLEMS_SYMPTOMS_MEAN).toEqual(EXPECTED_MEAN_SCORE) + }) + + it('should return the expected raw score for Life functioning difficulties', function () { + const EXPECTED_RAW_SCORE = 22 + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_RAW).toEqual( + EXPECTED_RAW_SCORE, + ) + }) + + it('should return the expected mean score for Life functioning difficulties', function () { + const EXPECTED_MEAN_SCORE = 1.83 + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_MEAN).toEqual( + EXPECTED_MEAN_SCORE, + ) + }) + + it('should return the expected raw score for Risk/harm', function () { + const EXPECTED_RAW_SCORE = 1 + expect(outcome.RISK_HARM_RAW).toEqual(EXPECTED_RAW_SCORE) + }) + + it('should return the expected mean score for Risk/harm', function () { + const EXPECTED_MEAN_SCORE = 0.17 + expect(outcome.RISK_HARM_MEAN).toEqual(EXPECTED_MEAN_SCORE) + }) + + it('should return the expected raw score for Total', function () { + const EXPECTED_RAW_SCORE = 28 + expect(outcome.TOTAL_RAW).toEqual(EXPECTED_RAW_SCORE) + }) + + it('should return the expected mean score for Total', function () { + const EXPECTED_MEAN_SCORE = 0.82 + expect(outcome.TOTAL_MEAN).toEqual(EXPECTED_MEAN_SCORE) + }) + }) + }) + + describe('a score is only calculated when all mandatory fields are entered', function () { + describe('when an empty response is passed', function () { + const outcome = core_om_calculation.calculate({ payload: {} }) + + describe('For the Subjective well-being deficits raw score', function () { + it('should return null result ', function () { + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_RAW).toEqual(null) + }) + }) + + describe('For the Subjective well-being deficits mean score', function () { + it('should return null result ', function () { + expect(outcome.SUBJECTIVE_WELL_BEING_DEFICITS_MEAN).toEqual(null) + }) + }) + + describe('For the Problems/symptoms raw score"', function () { + it('should return null result ', function () { + expect(outcome.PROBLEMS_SYMPTOMS_RAW).toEqual(null) + }) + }) + + describe('For the Problems/symptoms mean score', function () { + it('should return null result ', function () { + expect(outcome.PROBLEMS_SYMPTOMS_MEAN).toEqual(null) + }) + }) + + describe('For the Life functioning difficulties raw score"', function () { + it('should return null result ', function () { + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_RAW).toEqual(null) + }) + }) + + describe('For the Life functioning difficulties mean score', function () { + it('should return null result ', function () { + expect(outcome.LIFE_FUNCTIONING_DIFFICULTIES_MEAN).toEqual(null) + }) + }) + + describe('For the Risk/harm raw score"', function () { + it('should return null result ', function () { + expect(outcome.RISK_HARM_RAW).toEqual(null) + }) + }) + + describe('For the Risk/harm mean score', function () { + it('should return null result ', function () { + expect(outcome.RISK_HARM_MEAN).toEqual(null) + }) + }) + + describe('For the Total raw score"', function () { + it('should return null result ', function () { + expect(outcome.TOTAL_RAW).toEqual(null) + }) + }) + + describe('For the Total mean score', function () { + it('should return null result ', function () { + expect(outcome.TOTAL_MEAN).toEqual(null) + }) + }) + }) + }) + + describe('values entered by the user are checked to verify they are inside specified ranges', function () { + describe('when an answer is not a number', function () { + it('should throw an ZodError', function () { + expect(() => + core_om_calculation.calculate({ + payload: { + CORE_OM_Q01: "I'm not a number", + }, + }), + ).toThrow(ZodError) + }) + }) + describe('when an answer is below the expected range', function () { + it('should throw an ZodError', function () { + expect(() => + core_om_calculation.calculate({ + payload: { + CORE_OM_Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + describe('when an answer is above the expected range', function () { + it('should throw an ZodError', function () { + expect(() => + core_om_calculation.calculate({ + payload: { + CORE_OM_Q01: 6, + }, + }), + ).toThrow(ZodError) + }) + }) + }) +}) diff --git a/src/scores/core_om/core_om.ts b/src/scores/core_om/core_om.ts new file mode 100644 index 0000000..c927077 --- /dev/null +++ b/src/scores/core_om/core_om.ts @@ -0,0 +1,75 @@ +import { + CORE_OM_INPUTS, + CORE_OM_OUTPUT, + CORE_OM_SUBSCALE_ITEMS, +} from './definition' +import { ScoreType } from '../../types' +import { sum, pick, pickBy, isEmpty, round, size } from 'lodash' + +export const core_om: ScoreType = + { + name: 'Caregiver Strain Index (CSI)', + readmeLocation: __dirname, + inputSchema: CORE_OM_INPUTS, + outputSchema: CORE_OM_OUTPUT, + calculate: ({ data }) => { + const subjectiveWellBeingItems = pick( + data, + CORE_OM_SUBSCALE_ITEMS.SUBJECTIVE_WELLBEING, + ) + const problemsSymptomsItems = pick( + data, + CORE_OM_SUBSCALE_ITEMS.PROBLEMS_SYMPTOMS, + ) + const lifeFunctioningDifficultiesItems = pick( + data, + CORE_OM_SUBSCALE_ITEMS.LIFE_FUNCTIONING_DIFFICULTIES, + ) + const riskHarmItems = pick(data, CORE_OM_SUBSCALE_ITEMS.RISK_HARM) + + const calculateRawScore = ( + items: Record, + ): number | null => { + const definedItems = pickBy(items, value => value !== undefined) + + if (isEmpty(definedItems)) { + return null + } + + return sum(Object.values(definedItems)) + } + + const calculateMeanScore = ( + items: Record, + ): number | null => { + const rawScore = calculateRawScore(items) + + if (rawScore === null) { + return null + } + const ROUND_TO = 2 + return round(rawScore / size(items), ROUND_TO) + } + + return { + SUBJECTIVE_WELL_BEING_DEFICITS_RAW: calculateRawScore( + subjectiveWellBeingItems, + ), + SUBJECTIVE_WELL_BEING_DEFICITS_MEAN: calculateMeanScore( + subjectiveWellBeingItems, + ), + PROBLEMS_SYMPTOMS_RAW: calculateRawScore(problemsSymptomsItems), + PROBLEMS_SYMPTOMS_MEAN: calculateMeanScore(problemsSymptomsItems), + LIFE_FUNCTIONING_DIFFICULTIES_RAW: calculateRawScore( + lifeFunctioningDifficultiesItems, + ), + LIFE_FUNCTIONING_DIFFICULTIES_MEAN: calculateMeanScore( + lifeFunctioningDifficultiesItems, + ), + RISK_HARM_RAW: calculateRawScore(riskHarmItems), + RISK_HARM_MEAN: calculateMeanScore(riskHarmItems), + TOTAL_RAW: calculateRawScore(data), + TOTAL_MEAN: calculateMeanScore(data), + } + }, + } diff --git a/todo/core_om/definition/core_om_inputs.ts b/src/scores/core_om/definition/core_om_inputs.ts similarity index 66% rename from todo/core_om/definition/core_om_inputs.ts rename to src/scores/core_om/definition/core_om_inputs.ts index 8c5f78c..52604c1 100644 --- a/todo/core_om/definition/core_om_inputs.ts +++ b/src/scores/core_om/definition/core_om_inputs.ts @@ -1,305 +1,297 @@ -import type { InputType } from '../../../src/types/calculations.types' -import { NumberInputType } from '../../../src/types/calculations/inputs/calculation-inputs.types' +import { EnumNumberInputType, ScoreInputSchemaType } from '../../../types' +import { z } from 'zod' -const type: NumberInputType = { - type: 'number', - allowed_answers: [ - { value: 0, label: { en: 'Not at all', it: 'Per nulla' } }, - { value: 1, label: { en: 'Only occasionaly', it: 'Solo occasionalmente' } }, - { value: 2, label: { en: 'Sometimes', it: 'Ogni tanto' } }, - { value: 3, label: { en: 'Often', it: 'Spesso' } }, - { - value: 4, - label: { en: 'Most or all the time', it: 'Molto spesso o sempre' }, - }, - ], -} +const type = { + type: z + .union([ + z.literal(0), + z.literal(1), + z.literal(2), + z.literal(3), + z.literal(4), + ]) + .optional(), + uiOptions: { + options: [ + { value: 0, label: { en: 'Not at all', it: 'Per nulla' } }, + { + value: 1, + label: { en: 'Only occasionaly', it: 'Solo occasionalmente' }, + }, + { value: 2, label: { en: 'Sometimes', it: 'Ogni tanto' } }, + { value: 3, label: { en: 'Often', it: 'Spesso' } }, + { + value: 4, + label: { en: 'Most or all the time', it: 'Molto spesso o sempre' }, + }, + ], + }, +} satisfies EnumNumberInputType -const input_type_reversed: NumberInputType = { - type: 'number', - allowed_answers: [ - { value: 4, label: { en: 'Not at all', it: 'Per nulla' } }, - { value: 3, label: { en: 'Only occasionaly', it: 'Solo occasionalmente' } }, - { value: 2, label: { en: 'Sometimes', it: 'Ogni tanto' } }, - { value: 1, label: { en: 'Often', it: 'Spesso' } }, - { - value: 0, - label: { en: 'Most or all the time', it: 'Molto spesso o sempre' }, - }, - ], -} +const input_type_reversed = { + type: z + .union([ + z.literal(4), + z.literal(3), + z.literal(2), + z.literal(1), + z.literal(0), + ]) + .optional(), + uiOptions: { + options: [ + { value: 4, label: { en: 'Not at all', it: 'Per nulla' } }, + { + value: 3, + label: { en: 'Only occasionaly', it: 'Solo occasionalmente' }, + }, + { value: 2, label: { en: 'Sometimes', it: 'Ogni tanto' } }, + { value: 1, label: { en: 'Often', it: 'Spesso' } }, + { + value: 0, + label: { en: 'Most or all the time', it: 'Molto spesso o sempre' }, + }, + ], + }, +} satisfies EnumNumberInputType -export const CORE_OM_INPUTS: Array = [ - { - input_id: 'CORE_OM_Q01', +export const CORE_OM_INPUTS = { + CORE_OM_Q01: { label: { it: 'Mi sono sentito terribilmente solo e isolato', en: 'Over the last week... I have felt terribly alone and isolated', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q02', + CORE_OM_Q02: { label: { it: 'Mi sono sentito teso, ansioso o nervoso', en: 'Over the last week... I have felt tense, anxious or nervous', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q03', + CORE_OM_Q03: { label: { it: 'Ho sentito di avere qualcuno a cui rivolgermi per ricevere un sostegno quando ne ho avuto bisogno', en: 'Over the last week... I have felt I have someone to turn to for support when needed ', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q04', + CORE_OM_Q04: { label: { it: 'Mi sono sentito a posto con me stesso', en: 'Over the last week... I have felt O.K. about myself', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q05', + CORE_OM_Q05: { label: { it: 'Mi sono sentito completamente privo di energia e di entusiasmo', en: 'Over the last week... I have felt totally lacking in energy and enthusiasm ', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q06', + CORE_OM_Q06: { label: { it: 'Sono stato violento fisicamente verso altre persone', en: 'Over the last week... I have been physically violent to others', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q07', + CORE_OM_Q07: { label: { it: 'Mi sono sentito capace di adattarmi in caso di difficoltà', en: 'Over the last week... I have felt able to cope when things go wrong', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q08', + CORE_OM_Q08: { label: { it: 'Sono stato disturbato da malesseri, dolori o altri problemi fisici', en: 'Over the last week... I have been troubled by aches, pains or other physical problems', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q09', + CORE_OM_Q09: { label: { it: 'Ho pensato a farmi del male', en: 'Over the last week... I have thought of hurting myself', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q10', + CORE_OM_Q10: { label: { it: 'Non ho avuto la forza di parlare con le persone', en: 'Over the last week... Talking to people has felt too much for me', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q11', + CORE_OM_Q11: { label: { it: 'La tensione e l’ansia mi hanno impedito di fare cose importanti', en: 'Over the last week... Tension and anxiety have prevented me doing important things', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q12', + CORE_OM_Q12: { label: { it: 'Sono stato contento per le cose che ho fatto', en: 'Over the last week... I have been happy with the things I have done', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q13', + CORE_OM_Q13: { label: { it: 'Sono stato disturbato da pensieri e stati d’animo indesiderati', en: 'Over the last week... I have been disturbed by unwanted thoughts and feelings', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q14', + CORE_OM_Q14: { label: { it: 'Ho avuto voglia di piangere', en: 'Over the last week... I have felt like crying', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q15', + CORE_OM_Q15: { label: { it: 'Ho provato panico o terrore', en: 'Over the last week... I have felt panic or terror', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q16', + CORE_OM_Q16: { label: { it: 'Ho progettato di mettere fine alla mia vita', en: 'Over the last week... I made plans to end my life', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q17', + CORE_OM_Q17: { label: { it: 'Mi sono sentito sopraffatto dai miei problemi', en: 'Over the last week... I have felt overwhelmed by my problems', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q18', + CORE_OM_Q18: { label: { it: 'Ho avuto difficoltà ad addormentarmi o a mantenere il sonno', en: 'Over the last week... I have had difficulty getting to sleep or staying asleep', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q19', + CORE_OM_Q19: { label: { it: 'Ho provato calore o affetto per qualcuno', en: 'Over the last week... I have felt warmth or affection for someone', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q20', + CORE_OM_Q20: { label: { it: 'Mi è stato impossibile mettere da parte i miei problemi', en: 'Over the last week... My problems have been impossible to put to one side ', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q21', + CORE_OM_Q21: { label: { it: 'Sono stato in grado di fare la maggior parte delle cose che dovevo fare', en: 'Over the last week... I have been able to do most things I needed to ', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q22', + CORE_OM_Q22: { label: { it: 'Ho minacciato o intimorito qualcuno', en: 'Over the last week... I have threatened or intimidated another person ', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q23', + CORE_OM_Q23: { label: { it: 'Mi sono sentito affranto o senza speranza', en: 'Over the last week... I have felt despairing or hopeless', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q24', + CORE_OM_Q24: { label: { it: 'Ho pensato: “Sarebbe meglio essere morto”', en: 'Over the last week... I have thought it would be better if I were dead', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q25', + CORE_OM_Q25: { label: { it: 'Mi sono sentito criticato da altre persone', en: 'Over the last week... I have felt criticised by other people', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q26', + CORE_OM_Q26: { label: { it: 'Ho pensato di non avere amici', en: 'Over the last week... I have thought I have no friends', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q27', + CORE_OM_Q27: { label: { it: 'Mi sono sentito infelic', en: 'Over the last week... I have felt unhappy ', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q28', + CORE_OM_Q28: { label: { it: 'Sono stato turbato da immagini o ricordi indesiderati', en: 'Over the last week... Unwanted images or memories have been distressing me', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q29', + CORE_OM_Q29: { label: { it: 'Mi sono sentito irritato mentre ero con altre persone', en: 'Over the last week... I have been irritable when with other people ', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q30', + CORE_OM_Q30: { label: { it: 'Ho pensato che è mia la colpa dei problemi e delle difficoltà che ho', en: 'Over the last week... I have thought I am to blame for my problems and difficulties', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q31', + CORE_OM_Q31: { label: { it: 'Mi sono sentito ottimista per il mio futuro', en: 'Over the last week... I have felt optimistic about my future', }, - type: input_type_reversed, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q32', + CORE_OM_Q32: { label: { it: 'Ho ottenuto ciò che volevo', en: 'Over the last week... I have achieved the things I wanted to', }, - input_type, + ...input_type_reversed, }, - { - input_id: 'CORE_OM_Q33', + CORE_OM_Q33: { label: { it: 'Mi sono sentito umiliato o messo in imbarazzo da altre persone', en: 'Over the last week... I have felt humiliated or shamed by other people', }, - input_type, + ...type, }, - { - input_id: 'CORE_OM_Q34', + CORE_OM_Q34: { label: { it: 'Mi sono fatto del male fisicamente o ho messo seriamente in pericolo la mia salute', en: 'Over the last week... I have hurt myself physically or taken dangerous risks with my health', }, - input_type, + ...type, }, -] +} satisfies ScoreInputSchemaType diff --git a/src/scores/core_om/definition/core_om_output.ts b/src/scores/core_om/definition/core_om_output.ts new file mode 100644 index 0000000..9d4b0a2 --- /dev/null +++ b/src/scores/core_om/definition/core_om_output.ts @@ -0,0 +1,45 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const CORE_OM_OUTPUT = { + SUBJECTIVE_WELL_BEING_DEFICITS_RAW: { + label: { en: 'Subjective well-being deficits - Raw Score' }, + type: z.number(), + }, + SUBJECTIVE_WELL_BEING_DEFICITS_MEAN: { + label: { en: 'Subjective well-being deficits - Mean Score' }, + type: z.number(), + }, + PROBLEMS_SYMPTOMS_RAW: { + label: { en: 'Problems/symptoms - Raw Score' }, + type: z.number(), + }, + PROBLEMS_SYMPTOMS_MEAN: { + label: { en: 'Problems/symptoms - Mean Score' }, + type: z.number(), + }, + LIFE_FUNCTIONING_DIFFICULTIES_RAW: { + label: { en: 'Life functioning difficulties - Raw Score' }, + type: z.number(), + }, + LIFE_FUNCTIONING_DIFFICULTIES_MEAN: { + label: { en: 'Life functioning difficulties - Mean Score' }, + type: z.number(), + }, + RISK_HARM_RAW: { + label: { en: 'Risk/harm - Raw Score' }, + type: z.number(), + }, + RISK_HARM_MEAN: { + label: { en: 'Risk/harm - Mean Score' }, + type: z.number(), + }, + TOTAL_RAW: { + label: { en: 'Total - Raw Score' }, + type: z.number(), + }, + TOTAL_MEAN: { + label: { en: 'Total - Mean Score' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/core_om/definition/core_om_subscales.ts b/src/scores/core_om/definition/core_om_subscales.ts similarity index 100% rename from todo/core_om/definition/core_om_subscales.ts rename to src/scores/core_om/definition/core_om_subscales.ts diff --git a/todo/core_om/definition/index.ts b/src/scores/core_om/definition/index.ts similarity index 100% rename from todo/core_om/definition/index.ts rename to src/scores/core_om/definition/index.ts diff --git a/src/scores/cpdi/cpdi.test.ts b/src/scores/cpdi/cpdi.test.ts index 8227080..ab03f31 100644 --- a/src/scores/cpdi/cpdi.test.ts +++ b/src/scores/cpdi/cpdi.test.ts @@ -8,7 +8,6 @@ import { random_response, } from './__testdata__/cpdi_test_responses' import { cpdi } from './cpdi' -import { compose } from 'ramda' const CPDI_MIN_SCORE = 0 const CPDI_MEDIAN_SCORE = 50 @@ -72,7 +71,7 @@ describe('cpdi', function () { }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cpid_calculation.calculate({ payload: { @@ -84,7 +83,7 @@ describe('cpdi', function () { }) describe('when called with a response where there are answers out of the expected [0, 4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cpid_calculation.calculate({ payload: { @@ -95,7 +94,7 @@ describe('cpdi', function () { }) }) describe('when called with a response where there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cpid_calculation.calculate({ payload: { diff --git a/src/scores/cpdi/cpdi.ts b/src/scores/cpdi/cpdi.ts index 2f7a874..ed5ce78 100644 --- a/src/scores/cpdi/cpdi.ts +++ b/src/scores/cpdi/cpdi.ts @@ -1,6 +1,6 @@ import { CPDI_INPUTS, CPDI_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const cpdi: ScoreType = { name: 'Simple Shoulder Test (SST)', @@ -9,9 +9,9 @@ export const cpdi: ScoreType = { outputSchema: CPDI_OUTPUT, calculate: ({ data }) => { const MAX_SCORE_PER_QUESTION = 4 - const MAX_SCORE = Object.keys(data).length * MAX_SCORE_PER_QUESTION + const MAX_SCORE = Object.keys(CPDI_INPUTS).length * MAX_SCORE_PER_QUESTION - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) const percentageScore = (totalScore / MAX_SCORE) * 100 return { diff --git a/src/scores/dast_10/dast_10.test.ts b/src/scores/dast_10/dast_10.test.ts index e30db59..c2327cb 100644 --- a/src/scores/dast_10/dast_10.test.ts +++ b/src/scores/dast_10/dast_10.test.ts @@ -58,7 +58,7 @@ describe('dast_10', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dast10_calculation.calculate({ payload: { diff --git a/src/scores/dast_10/dast_10.ts b/src/scores/dast_10/dast_10.ts index f045208..cb56229 100644 --- a/src/scores/dast_10/dast_10.ts +++ b/src/scores/dast_10/dast_10.ts @@ -4,7 +4,7 @@ import { DAST10_INTERPRETATION_TABLE, } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const dast_10: ScoreType = { name: 'Drug Abuse Screening Test (DAST-10)', @@ -23,7 +23,7 @@ export const dast_10: ScoreType = { } } - const totalScore = _.sum(definedInputs) + const totalScore = sum(definedInputs) return { DAST10_SCORE: totalScore, diff --git a/src/scores/dn4/dn4.test.ts b/src/scores/dn4/dn4.test.ts index b17a459..47ce25a 100644 --- a/src/scores/dn4/dn4.test.ts +++ b/src/scores/dn4/dn4.test.ts @@ -63,7 +63,7 @@ describe('dn4', function () { }) describe('when an answer is not a boolean', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dn4_calculation.calculate({ payload: { diff --git a/src/scores/dn4/dn4.ts b/src/scores/dn4/dn4.ts index 3c471eb..2e188f1 100644 --- a/src/scores/dn4/dn4.ts +++ b/src/scores/dn4/dn4.ts @@ -1,6 +1,6 @@ import { DN4_INPUTS, DN4_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const dn4: ScoreType = { name: 'Douleur Neuropathique 4 (DN4)', @@ -31,8 +31,8 @@ export const dn4: ScoreType = { v => v !== undefined, ) - const patientInterviewScore = _.sum(definedPatientInterviewInputs) - const patientExaminationScore = _.sum(definedPatientExaminationInputs) + const patientInterviewScore = sum(definedPatientInterviewInputs) + const patientExaminationScore = sum(definedPatientExaminationInputs) const patientTotalScore = patientInterviewScore + patientExaminationScore return { diff --git a/src/scores/eq5d/3_level/eq5d_3l.test.ts b/src/scores/eq5d/3_level/eq5d_3l.test.ts index 6cbd680..efba952 100644 --- a/src/scores/eq5d/3_level/eq5d_3l.test.ts +++ b/src/scores/eq5d/3_level/eq5d_3l.test.ts @@ -129,7 +129,7 @@ describe('eq5d_3l', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eq5d_3l_calculation.calculate({ payload: { @@ -140,7 +140,7 @@ describe('eq5d_3l', function () { }) }) describe('when an answer is below the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eq5d_3l_calculation.calculate({ payload: { @@ -151,7 +151,7 @@ describe('eq5d_3l', function () { }) }) describe('when an answer is above the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eq5d_3l_calculation.calculate({ payload: { diff --git a/src/scores/eq5d/3_level/eq5d_3l.ts b/src/scores/eq5d/3_level/eq5d_3l.ts index 0d2f1bb..173df92 100644 --- a/src/scores/eq5d/3_level/eq5d_3l.ts +++ b/src/scores/eq5d/3_level/eq5d_3l.ts @@ -1,6 +1,5 @@ import { EQ5D_3L_INPUTS, EQ5D_3L_OUTPUT } from './definition' import { ScoreType } from '../../../types' -import _ from 'lodash' export const eq5d_3l: ScoreType = { diff --git a/src/scores/eq5d/5_level/eq5d_5l.test.ts b/src/scores/eq5d/5_level/eq5d_5l.test.ts index 2035b0f..b85eab7 100644 --- a/src/scores/eq5d/5_level/eq5d_5l.test.ts +++ b/src/scores/eq5d/5_level/eq5d_5l.test.ts @@ -158,7 +158,7 @@ describe('eq5d_5l', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eq5d_5l_calculation.calculate({ payload: { @@ -169,7 +169,7 @@ describe('eq5d_5l', function () { }) }) describe('when an answer is below the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eq5d_5l_calculation.calculate({ payload: { @@ -180,7 +180,7 @@ describe('eq5d_5l', function () { }) }) describe('when an answer is above the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eq5d_5l_calculation.calculate({ payload: { diff --git a/src/scores/eq5d/5_level/eq5d_5l.ts b/src/scores/eq5d/5_level/eq5d_5l.ts index 68e13a1..90a2fbe 100644 --- a/src/scores/eq5d/5_level/eq5d_5l.ts +++ b/src/scores/eq5d/5_level/eq5d_5l.ts @@ -1,6 +1,5 @@ import { EQ5D_5L_INPUTS, EQ5D_5L_OUTPUT } from './definition' import { ScoreType } from '../../../types' -import _ from 'lodash' import { calculate_be_utility_value } from './calculate_utility_values/Belgium/calculate_be_utility_value' export const eq5d_5l: ScoreType = diff --git a/todo/ess/README.md b/src/scores/ess/README.md similarity index 100% rename from todo/ess/README.md rename to src/scores/ess/README.md diff --git a/todo/ess/__testdata__/ess_test_responses.ts b/src/scores/ess/__testdata__/ess_test_responses.ts similarity index 100% rename from todo/ess/__testdata__/ess_test_responses.ts rename to src/scores/ess/__testdata__/ess_test_responses.ts diff --git a/src/scores/ess/definition/ess_inputs.ts b/src/scores/ess/definition/ess_inputs.ts new file mode 100644 index 0000000..c482a51 --- /dev/null +++ b/src/scores/ess/definition/ess_inputs.ts @@ -0,0 +1,94 @@ +import { z } from 'zod' +import { EnumNumberInputType, ScoreInputSchemaType } from '../../../types' + +const type = { + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ + { + value: 0, + label: { nl: 'Ik word niet doezelig/slaperig', en: 'Would never dose' }, + }, + { + value: 1, + label: { + nl: 'Lichte kans dat ik doezelig/slaperig word', + en: 'Slight chance of dozing', + }, + }, + { + value: 2, + label: { + nl: 'Matige kans dat ik doezelig/slaperig word', + en: 'Moderate chance of dozing', + }, + }, + { + value: 3, + label: { + nl: 'Hoge kans dat ik doezelig/slaperig word', + en: 'High chance of dozing', + }, + }, + ], + }, +} satisfies EnumNumberInputType + +export const ESS_INPUTS = { + ESS_Q1: { + label: { + nl: 'Tijdens zitten en lezen', + en: 'Sitting and reading', + }, + ...type, + }, + ESS_Q2: { + label: { + nl: 'Tijdens televisie kijken', + en: 'Watching TV', + }, + ...type, + }, + ESS_Q3: { + label: { + nl: 'Zitten in een openbare instelling (zoals theater)', + en: 'Sitting still in a public place (e.g. a theatre, a cinema or a meeting)', + }, + ...type, + }, + ESS_Q4: { + label: { + nl: 'Langer dan 1 uur zittend als passagier in de auto', + en: 'As a passenger in a car for an hour without a break', + }, + ...type, + }, + ESS_Q5: { + label: { + nl: 'Tijdens rust in de namiddag ', + en: 'Lying down to rest in the afternoon when the circumstances allow', + }, + ...type, + }, + ESS_Q6: { + label: { + nl: 'Zitten en praten met iemand', + en: 'Sitting and talking to someone', + }, + ...type, + }, + ESS_Q7: { + label: { + nl: 'Na de lunch', + en: 'Sitting quietly after lunch without having drunk alcohol', + }, + ...type, + }, + ESS_Q8: { + label: { + nl: 'In de auto in een stilstaande file', + en: 'In a car or bus while stopped for a few minutes in traffic', + }, + ...type, + }, +} satisfies ScoreInputSchemaType diff --git a/src/scores/ess/definition/ess_output.ts b/src/scores/ess/definition/ess_output.ts new file mode 100644 index 0000000..be13f98 --- /dev/null +++ b/src/scores/ess/definition/ess_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const ESS_OUTPUT = { + ess: { + label: { en: 'Total ESS score' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/ess/definition/index.ts b/src/scores/ess/definition/index.ts similarity index 100% rename from todo/ess/definition/index.ts rename to src/scores/ess/definition/index.ts diff --git a/src/scores/ess/ess.test.ts b/src/scores/ess/ess.test.ts new file mode 100644 index 0000000..ebc9617 --- /dev/null +++ b/src/scores/ess/ess.test.ts @@ -0,0 +1,125 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + max_response, + median_response, + min_response, + random_response, +} from './__testdata__/ess_test_responses' +import { ess } from './ess' + +const ESS_MIN_SCORE = 0 +const ESS_MID_SCORE = 12 +const ESS_MAX_SCORE = 24 + +const ess_calculation = new Score(ess) + +describe('ess', function () { + it('ess calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('ess') + }) + + describe('basic assumptions', function () { + const outcome = ess_calculation.calculate({ payload: min_response }) + + it('should return 1 calculation result', function () { + expect(Object.keys(outcome).length).toEqual(1) + }) + + it('should have the expected calculation id', function () { + const EXPECTED_CALCULATION_ID = ['ess'] + 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 = [ + 'ESS_Q1', + 'ESS_Q2', + 'ESS_Q3', + 'ESS_Q4', + 'ESS_Q5', + 'ESS_Q6', + 'ESS_Q7', + 'ESS_Q8', + ] + + const configured_input_ids = Object.keys(ess_calculation.inputSchema) + + expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) + }) + }) + describe('when an answer is below the expected [0,4] range', function () { + it('should throw an ZodError', function () { + expect(() => + ess_calculation.calculate({ payload: { ESS_Q1: -1 } }), + ).toThrow(ZodError) + }) + }) + + describe('when called with a response where there are answers out of the expected [0, 4] range', function () { + it('should throw an ZodError', function () { + expect(() => + ess_calculation.calculate({ payload: { ESS_Q1: 5 } }), + ).toThrow(ZodError) + }) + }) + describe('when called with a response where there are non-numerical answers', function () { + it('should throw an ZodError', function () { + expect(() => + ess_calculation.calculate({ + payload: { ESS_Q1: "I'm not a number" }, + }), + ).toThrow(ZodError) + }) + }) + describe('when called with an empty response', function () { + it('should throw a ZodError', function () { + expect(() => ess_calculation.calculate({ payload: {} })).toThrow( + ZodError, + ) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with a minimum response', function () { + it('should return the minimum score', function () { + const score = ess_calculation.calculate({ payload: min_response }) + + expect(score.ess).toEqual(ESS_MIN_SCORE) + }) + }) + + describe('when called with a median response', function () { + it('should return the median score', function () { + const score = ess_calculation.calculate({ payload: median_response }) + + expect(score.ess).toEqual(ESS_MID_SCORE) + }) + }) + + describe('when called with a maximum response', function () { + it('should return the maximum score', function () { + const score = ess_calculation.calculate({ payload: max_response }) + + expect(score.ess).toEqual(ESS_MAX_SCORE) + }) + }) + + describe('when called with a random response', function () { + it('should return the expected score', function () { + const score = ess_calculation.calculate({ payload: random_response }) + + const EXPECTED_SCORE = 13 + + expect(score.ess).toEqual(EXPECTED_SCORE) + }) + }) + }) +}) diff --git a/src/scores/ess/ess.ts b/src/scores/ess/ess.ts new file mode 100644 index 0000000..9f56af3 --- /dev/null +++ b/src/scores/ess/ess.ts @@ -0,0 +1,14 @@ +import { ESS_INPUTS, ESS_OUTPUT } from './definition' +import { ScoreType } from '../../types' +import { sum } from 'lodash' + +export const ess: ScoreType = { + name: 'Epworth Sleepiness Scale (ESS)', + readmeLocation: __dirname, + inputSchema: ESS_INPUTS, + outputSchema: ESS_OUTPUT, + calculate: ({ data }) => { + const totalScore = sum(Object.values(data)) + return { ess: totalScore } + }, +} diff --git a/src/scores/fnd/fnd.test.ts b/src/scores/fnd/fnd.test.ts index a678d45..5e9fe89 100644 --- a/src/scores/fnd/fnd.test.ts +++ b/src/scores/fnd/fnd.test.ts @@ -49,7 +49,7 @@ describe('fnd', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => fnd_calculation.calculate({ payload: { diff --git a/src/scores/fnd/fnd.ts b/src/scores/fnd/fnd.ts index 148059a..4b3e260 100644 --- a/src/scores/fnd/fnd.ts +++ b/src/scores/fnd/fnd.ts @@ -1,6 +1,6 @@ import { FND_INPUTS, FND_OUTPUT, FND_INTERPRATION_TABLE } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const fnd: ScoreType = { name: 'Fagerstrom Test for Nicotine Dependence (FND)', @@ -8,7 +8,7 @@ export const fnd: ScoreType = { inputSchema: FND_INPUTS, outputSchema: FND_OUTPUT, calculate: ({ data }) => { - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) return { FAGERSTROM_TOTAL_SCORE: totalScore, FAGERSTROM_DEPENDENCE_LEVEL: diff --git a/todo/forgotten_joint_score_12/hip/README.md b/src/scores/forgotten_joint_score_12/hip/README.md similarity index 99% rename from todo/forgotten_joint_score_12/hip/README.md rename to src/scores/forgotten_joint_score_12/hip/README.md index 71bc655..49852b9 100644 --- a/todo/forgotten_joint_score_12/hip/README.md +++ b/src/scores/forgotten_joint_score_12/hip/README.md @@ -26,5 +26,6 @@ If more than four of the answers are missing also the total score should be trea The total score ranges from 0 to 100; a high score indicates good outcome. ## References + [1] Joint awareness after unicompartmental knee arthroplasty and total knee arthroplasty: a systematic review and meta-analysis of cohort studies. Tripathy SK, Varghese P, Srinivasan A, Goyal T, Purudappa PP, Sen RK, Chandrappa MH. Knee Surg Sports Traumatol Arthrosc. 2020 Oct 19. [2] Evaluation of joint awareness after acetabular fracture: Validation of the Forgotten Joint Score according to the COSMIN checklist protocol. Freigang V, Weber J, Mueller K, Pfeifer C, Worlicek M, Alt V, Baumann FM. World J Orthop. 2021 Feb 18;12(2):69-81. \ No newline at end of file diff --git a/todo/forgotten_joint_score_12/hip/__testdata__/forgotten_joint_score_12_hip_test_responses.ts b/src/scores/forgotten_joint_score_12/hip/__testdata__/forgotten_joint_score_12_hip_test_responses.ts similarity index 100% rename from todo/forgotten_joint_score_12/hip/__testdata__/forgotten_joint_score_12_hip_test_responses.ts rename to src/scores/forgotten_joint_score_12/hip/__testdata__/forgotten_joint_score_12_hip_test_responses.ts diff --git a/todo/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_inputs.ts b/src/scores/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_inputs.ts similarity index 57% rename from todo/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_inputs.ts rename to src/scores/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_inputs.ts index 1dbb628..fae4b07 100644 --- a/todo/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_inputs.ts +++ b/src/scores/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_inputs.ts @@ -1,139 +1,137 @@ -import type { InputType } from '../../../../src/types/calculations.types' -import { NumberInputType } from '../../../../src/types/calculations/inputs/calculation-inputs.types' +import { z } from 'zod' +import { EnumNumberInputType, ScoreInputSchemaType } from '../../../../types' -const type: NumberInputType = { - type: 'number', - allowed_answers: [ - { - value: 1, - label: { nl: 'Nooit', en: '' }, - }, - { - value: 2, - label: { - nl: 'Bijna nooit', - en: '', +const type = { + type: z + .union([ + z.literal(1), + z.literal(2), + z.literal(3), + z.literal(4), + z.literal(5), + ]) + .optional(), + uiOptions: { + options: [ + { + value: 1, + label: { nl: 'Nooit', en: '' }, }, - }, - { - value: 3, - label: { - nl: 'Zelden', - en: '', + { + value: 2, + label: { + nl: 'Bijna nooit', + en: '', + }, }, - }, - { - value: 4, - label: { - nl: 'Soms', - en: '', + { + value: 3, + label: { + nl: 'Zelden', + en: '', + }, }, - }, - { - value: 5, - label: { - nl: 'Meestal', - en: '', + { + value: 4, + label: { + nl: 'Soms', + en: '', + }, }, - }, - ], -} + { + value: 5, + label: { + nl: 'Meestal', + en: '', + }, + }, + ], + }, +} satisfies EnumNumberInputType -export const FJS_HIP_INPUTS: Array = [ - { - input_id: 'Q01', +export const FJS_HIP_INPUTS = { + Q01: { label: { nl: "Bent u zich bewust van uw heupgewricht 's nachts in bed?", en: '', }, - input_type, + ...type, }, - { - input_id: 'Q02', + Q02: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u langer dan een uur op een stoel zit?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q03', + Q03: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u langer dan 15 minuten wandelt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q04', + Q04: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u een bad/douche neemt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q05', + Q05: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u met de auto reist?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q06', + Q06: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u de trap opgaat?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q07', + Q07: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u op een oneffen ondergrond wandelt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q08', + Q08: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u opstaat vanuit een laagzittende positie?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q09', + Q09: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u lange tijd staat?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q10', + Q10: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u huishoudelijke taken uitvoert of tuiniert?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q11', + Q11: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u een korte wandeling of trektocht maakt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q12', + Q12: { label: { nl: 'Bent u zich bewust van uw heupgewricht wanneer u uw favoriete sport beoefent?', en: '', }, - input_type, + ...type, }, -] +} satisfies ScoreInputSchemaType diff --git a/src/scores/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_output.ts b/src/scores/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_output.ts new file mode 100644 index 0000000..a94fdf7 --- /dev/null +++ b/src/scores/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../../types' + +export const FJS_HIP_OUTPUT = { + FORGOTTEN_JOINT_SCORE_HIP: { + label: { en: 'Forgotten Joint Score - Hip' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/forgotten_joint_score_12/hip/definition/index.ts b/src/scores/forgotten_joint_score_12/hip/definition/index.ts similarity index 100% rename from todo/forgotten_joint_score_12/hip/definition/index.ts rename to src/scores/forgotten_joint_score_12/hip/definition/index.ts diff --git a/src/scores/forgotten_joint_score_12/hip/forgotten_joint_score_12_hip.test.ts b/src/scores/forgotten_joint_score_12/hip/forgotten_joint_score_12_hip.test.ts new file mode 100644 index 0000000..f9ccbc8 --- /dev/null +++ b/src/scores/forgotten_joint_score_12/hip/forgotten_joint_score_12_hip.test.ts @@ -0,0 +1,161 @@ +import { ZodError } from 'zod' +import { Score } from '../../../classes' +import { ScoreLibrary } from '../../library' +import { + best_response, + median_response, + random_response, + worst_response, +} from './__testdata__/forgotten_joint_score_12_hip_test_responses' +import { forgotten_joint_score_hip } from './forgotten_joint_score_hip_12' + +const BEST_FJS_SCORE = 100 +const MEDIAN_FJS_SCORE = 50 +const WORST_FJS_SCORE = 0 + +const fjs_calculation = new Score(forgotten_joint_score_hip) + +describe('forgotten_joint_score_hip', function () { + it('forgotten_joint_score_hip calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('forgotten_joint_score_hip') + }) + + describe('basic assumptions', function () { + const outcome = fjs_calculation.calculate({ payload: best_response }) + + it('should return 1 calculation result', function () { + expect(Object.keys(outcome).length).toEqual(1) + }) + + it('should have the expected calculation result id', function () { + const EXPECTED_CALCULATION_ID = ['FORGOTTEN_JOINT_SCORE_HIP'] + + 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 = [ + 'Q01', + 'Q02', + 'Q03', + 'Q04', + 'Q05', + 'Q06', + 'Q07', + 'Q08', + 'Q09', + 'Q10', + 'Q11', + 'Q12', + ] + + const configured_input_ids = Object.keys(fjs_calculation.inputSchema) + + expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) + }) + }) + + describe('when an answer is below the expected [1,5] range', function () { + it('should throw an ZodError', function () { + expect(() => + fjs_calculation.calculate({ + payload: { + Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with a response where there are answers out of the expected [1, 5] range', function () { + it('should throw an ZodError', function () { + expect(() => + fjs_calculation.calculate({ + payload: { + Q01: 6, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with a response where there are non-numerical answers', function () { + it('should throw an ZodError', function () { + expect(() => + fjs_calculation.calculate({ + payload: { + Q01: "I'm not a number", + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with an empty response', function () { + it('should return null result', function () { + const outcome = fjs_calculation.calculate({ payload: {} }) + expect(outcome.FORGOTTEN_JOINT_SCORE_HIP).toEqual(null) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with the best response', function () { + it('should return the best FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: best_response }) + expect(outcome.FORGOTTEN_JOINT_SCORE_HIP).toEqual(BEST_FJS_SCORE) + }) + }) + + describe('when called with the median response', function () { + it('should return the median FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: median_response }) + expect(outcome.FORGOTTEN_JOINT_SCORE_HIP).toEqual(MEDIAN_FJS_SCORE) + }) + }) + + describe('when called with the worst response', function () { + it('should return the worst FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: worst_response }) + expect(outcome.FORGOTTEN_JOINT_SCORE_HIP).toEqual(WORST_FJS_SCORE) + }) + }) + + describe('when called with a random response', function () { + it('should return the expected FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: random_response }) + const EXPECTED_SCORE = 65 + expect(outcome.FORGOTTEN_JOINT_SCORE_HIP).toEqual(EXPECTED_SCORE) + }) + }) + + describe('when called with an incomplete response', function () { + it('should return the expected FJS score', function () { + const outcome = fjs_calculation.calculate({ + // Mean = 2.625 * 12 = 31.5 + payload: { + Q01: 1, + Q02: 2, + Q03: 3, + Q04: 4, + Q05: 5, + Q06: 1, + Q07: 2, + Q08: 3, + Q09: undefined, + Q10: undefined, + Q11: undefined, + Q12: undefined, + }, + }) + const EXPECTED_SCORE = 59 + expect(outcome.FORGOTTEN_JOINT_SCORE_HIP).toEqual(EXPECTED_SCORE) + }) + }) + }) +}) diff --git a/src/scores/forgotten_joint_score_12/hip/forgotten_joint_score_hip_12.ts b/src/scores/forgotten_joint_score_12/hip/forgotten_joint_score_hip_12.ts new file mode 100644 index 0000000..03e786e --- /dev/null +++ b/src/scores/forgotten_joint_score_12/hip/forgotten_joint_score_hip_12.ts @@ -0,0 +1,47 @@ +import { FJS_HIP_INPUTS, FJS_HIP_OUTPUT } from './definition' +import { ScoreType } from '../../../types' +import { sum, mean } from 'lodash' + +export const forgotten_joint_score_hip: ScoreType< + typeof FJS_HIP_INPUTS, + typeof FJS_HIP_OUTPUT +> = { + name: 'Forgotten Joint Score – 12 (FJS-12) - Hip', + readmeLocation: __dirname, + inputSchema: FJS_HIP_INPUTS, + outputSchema: FJS_HIP_OUTPUT, + calculate: ({ data }) => { + const MAX_INVALID_ANSWERS = 4 + const totalNbOfQuestions = Object.keys(FJS_HIP_INPUTS).length + + const nbrOfValidAnsweredQuestions = Object.values(data).filter( + v => v !== undefined, + ).length + const nbrOfInvalidAnsweredQuestions = + totalNbOfQuestions - nbrOfValidAnsweredQuestions + + if (nbrOfInvalidAnsweredQuestions > MAX_INVALID_ANSWERS) { + return { FORGOTTEN_JOINT_SCORE_HIP: null } + } + + const getWipScore = () => { + if (nbrOfValidAnsweredQuestions === totalNbOfQuestions) { + return sum(Object.values(data)) + } + + /** + * In case of missing answers (<= 4), the mean of the answered items is used + * instead of the sum of all items and multiplied by 12 (i.e. the missing values are + * replaced with the mean of the completed items). + */ + const meanOfAnsweredQuestions = mean( + Object.values(data).filter(v => v !== undefined), + ) + return meanOfAnsweredQuestions * 12 + } + + const fjsScore = 100 - ((getWipScore() - 12) / 48) * 100 + + return { FORGOTTEN_JOINT_SCORE_HIP: Math.round(fjsScore) } + }, +} diff --git a/todo/forgotten_joint_score_12/index.ts b/src/scores/forgotten_joint_score_12/index.ts similarity index 100% rename from todo/forgotten_joint_score_12/index.ts rename to src/scores/forgotten_joint_score_12/index.ts diff --git a/todo/forgotten_joint_score_12/knee/README.md b/src/scores/forgotten_joint_score_12/knee/README.md similarity index 100% rename from todo/forgotten_joint_score_12/knee/README.md rename to src/scores/forgotten_joint_score_12/knee/README.md diff --git a/todo/forgotten_joint_score_12/knee/__testdata__/forgotten_joint_score_12_knee_test_responses.ts b/src/scores/forgotten_joint_score_12/knee/__testdata__/forgotten_joint_score_12_knee_test_responses.ts similarity index 100% rename from todo/forgotten_joint_score_12/knee/__testdata__/forgotten_joint_score_12_knee_test_responses.ts rename to src/scores/forgotten_joint_score_12/knee/__testdata__/forgotten_joint_score_12_knee_test_responses.ts diff --git a/todo/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_inputs.ts b/src/scores/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_inputs.ts similarity index 57% rename from todo/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_inputs.ts rename to src/scores/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_inputs.ts index 3a991f5..aa54486 100644 --- a/todo/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_inputs.ts +++ b/src/scores/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_inputs.ts @@ -1,139 +1,137 @@ -import type { InputType } from '../../../../src/types/calculations.types' -import { NumberInputType } from '../../../../src/types/calculations/inputs/calculation-inputs.types' +import { z } from 'zod' +import { EnumNumberInputType } from '../../../../types' -const type: NumberInputType = { - type: 'number', - allowed_answers: [ - { - value: 1, - label: { nl: 'Nooit', en: '' }, - }, - { - value: 2, - label: { - nl: 'Bijna nooit', - en: '', +const type = { + type: z + .union([ + z.literal(1), + z.literal(2), + z.literal(3), + z.literal(4), + z.literal(5), + ]) + .optional(), + uiOptions: { + options: [ + { + value: 1, + label: { nl: 'Nooit', en: '' }, }, - }, - { - value: 3, - label: { - nl: 'Zelden', - en: '', + { + value: 2, + label: { + nl: 'Bijna nooit', + en: '', + }, }, - }, - { - value: 4, - label: { - nl: 'Soms', - en: '', + { + value: 3, + label: { + nl: 'Zelden', + en: '', + }, }, - }, - { - value: 5, - label: { - nl: 'Meestal', - en: '', + { + value: 4, + label: { + nl: 'Soms', + en: '', + }, }, - }, - ], -} + { + value: 5, + label: { + nl: 'Meestal', + en: '', + }, + }, + ], + }, +} satisfies EnumNumberInputType -export const FJS_KNEE_INPUTS: Array = [ - { - input_id: 'Q01', +export const FJS_KNEE_INPUTS = { + Q01: { label: { nl: "Bent u zich bewust van uw kniegewricht 's nachts in bed?", en: '', }, - input_type, + ...type, }, - { - input_id: 'Q02', + Q02: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u langer dan een uur op een stoel zit?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q03', + Q03: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u langer dan 15 minuten wandelt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q04', + Q04: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u een bad/douche neemt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q05', + Q05: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u met de auto reist?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q06', + Q06: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u de trap opgaat?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q07', + Q07: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u op een oneffen ondergrond wandelt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q08', + Q08: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u opstaat vanuit een laagzittende positie?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q09', + Q09: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u lange tijd staat?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q10', + Q10: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u huishoudelijke taken uitvoert of tuiniert?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q11', + Q11: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u een korte wandeling of trektocht maakt?', en: '', }, - input_type, + ...type, }, - { - input_id: 'Q12', + Q12: { label: { nl: 'Bent u zich bewust van uw kniegewricht wanneer u uw favoriete sport beoefent?', en: '', }, - input_type, + ...type, }, -] +} diff --git a/src/scores/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_output.ts b/src/scores/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_output.ts new file mode 100644 index 0000000..fd498c5 --- /dev/null +++ b/src/scores/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../../types' + +export const FJS_KNEE_OUTPUT = { + FORGOTTEN_JOINT_SCORE_KNEE: { + label: { en: 'Forgotten Joint Score - Knee' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/forgotten_joint_score_12/knee/definition/index.ts b/src/scores/forgotten_joint_score_12/knee/definition/index.ts similarity index 100% rename from todo/forgotten_joint_score_12/knee/definition/index.ts rename to src/scores/forgotten_joint_score_12/knee/definition/index.ts diff --git a/src/scores/forgotten_joint_score_12/knee/forgotten_joint_score_12_knee.test.ts b/src/scores/forgotten_joint_score_12/knee/forgotten_joint_score_12_knee.test.ts new file mode 100644 index 0000000..4a7590b --- /dev/null +++ b/src/scores/forgotten_joint_score_12/knee/forgotten_joint_score_12_knee.test.ts @@ -0,0 +1,161 @@ +import { ZodError } from 'zod' +import { Score } from '../../../classes' +import { ScoreLibrary } from '../../library' +import { + best_response, + median_response, + random_response, + worst_response, +} from './__testdata__/forgotten_joint_score_12_knee_test_responses' +import { forgotten_joint_score_knee } from './forgotten_joint_score_knee_12' + +const BEST_FJS_SCORE = 100 +const MEDIAN_FJS_SCORE = 50 +const WORST_FJS_SCORE = 0 + +const fjs_calculation = new Score(forgotten_joint_score_knee) + +describe('forgotten_joint_score_knee', function () { + it('forgotten_joint_score_knee calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('forgotten_joint_score_knee') + }) + + describe('basic assumptions', function () { + const outcome = fjs_calculation.calculate({ payload: best_response }) + + it('should return 1 calculation result', function () { + expect(Object.keys(outcome).length).toEqual(1) + }) + + it('should have the expected calculation result id', function () { + const EXPECTED_CALCULATION_ID = ['FORGOTTEN_JOINT_SCORE_KNEE'] + + 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 = [ + 'Q01', + 'Q02', + 'Q03', + 'Q04', + 'Q05', + 'Q06', + 'Q07', + 'Q08', + 'Q09', + 'Q10', + 'Q11', + 'Q12', + ] + + const configured_input_ids = Object.keys(fjs_calculation.inputSchema) + + expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) + }) + }) + + describe('when an answer is below the expected [1,5] range', function () { + it('should throw an ZodError', function () { + expect(() => + fjs_calculation.calculate({ + payload: { + Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with a response where there are answers out of the expected [1, 5] range', function () { + it('should throw an ZodError', function () { + expect(() => + fjs_calculation.calculate({ + payload: { + Q01: 6, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with a response where there are non-numerical answers', function () { + it('should throw an ZodError', function () { + expect(() => + fjs_calculation.calculate({ + payload: { + Q01: "I'm not a number", + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with an empty response', function () { + it('should return null result', function () { + const outcome = fjs_calculation.calculate({ payload: {} }) + expect(outcome.FORGOTTEN_JOINT_SCORE_KNEE).toEqual(null) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with the best response', function () { + it('should return the best FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: best_response }) + expect(outcome.FORGOTTEN_JOINT_SCORE_KNEE).toEqual(BEST_FJS_SCORE) + }) + }) + + describe('when called with the median response', function () { + it('should return the median FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: median_response }) + expect(outcome.FORGOTTEN_JOINT_SCORE_KNEE).toEqual(MEDIAN_FJS_SCORE) + }) + }) + + describe('when called with the worst response', function () { + it('should return the worst FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: worst_response }) + expect(outcome.FORGOTTEN_JOINT_SCORE_KNEE).toEqual(WORST_FJS_SCORE) + }) + }) + + describe('when called with a random response', function () { + it('should return the expected FJS score', function () { + const outcome = fjs_calculation.calculate({ payload: random_response }) + const EXPECTED_SCORE = 65 + expect(outcome.FORGOTTEN_JOINT_SCORE_KNEE).toEqual(EXPECTED_SCORE) + }) + }) + + describe('when called with an incomplete response', function () { + it('should return the expected FJS score', function () { + const outcome = fjs_calculation.calculate({ + // Mean = 2.625 * 12 = 31.5 + payload: { + Q01: 1, + Q02: 2, + Q03: 3, + Q04: 4, + Q05: 5, + Q06: 1, + Q07: 2, + Q08: 3, + Q09: undefined, + Q10: undefined, + Q11: undefined, + Q12: undefined, + }, + }) + const EXPECTED_SCORE = 59 + expect(outcome.FORGOTTEN_JOINT_SCORE_KNEE).toEqual(EXPECTED_SCORE) + }) + }) + }) +}) diff --git a/src/scores/forgotten_joint_score_12/knee/forgotten_joint_score_knee_12.ts b/src/scores/forgotten_joint_score_12/knee/forgotten_joint_score_knee_12.ts new file mode 100644 index 0000000..0a2a2b7 --- /dev/null +++ b/src/scores/forgotten_joint_score_12/knee/forgotten_joint_score_knee_12.ts @@ -0,0 +1,47 @@ +import { FJS_KNEE_INPUTS, FJS_KNEE_OUTPUT } from './definition' +import { ScoreType } from '../../../types' +import { sum, mean } from 'lodash' + +export const forgotten_joint_score_knee: ScoreType< + typeof FJS_KNEE_INPUTS, + typeof FJS_KNEE_OUTPUT +> = { + name: 'Forgotten Joint Score – 12 (FJS-12) - Knee', + readmeLocation: __dirname, + inputSchema: FJS_KNEE_INPUTS, + outputSchema: FJS_KNEE_OUTPUT, + calculate: ({ data }) => { + const MAX_INVALID_ANSWERS = 4 + const totalNbOfQuestions = Object.keys(FJS_KNEE_INPUTS).length + + const nbrOfValidAnsweredQuestions = Object.values(data).filter( + v => v !== undefined, + ).length + const nbrOfInvalidAnsweredQuestions = + totalNbOfQuestions - nbrOfValidAnsweredQuestions + + if (nbrOfInvalidAnsweredQuestions > MAX_INVALID_ANSWERS) { + return { FORGOTTEN_JOINT_SCORE_KNEE: null } + } + + const getWipScore = () => { + if (nbrOfValidAnsweredQuestions === totalNbOfQuestions) { + return sum(Object.values(data)) + } + + /** + * In case of missing answers (<= 4), the mean of the answered items is used + * instead of the sum of all items and multiplied by 12 (i.e. the missing values are + * replaced with the mean of the completed items). + */ + const meanOfAnsweredQuestions = mean( + Object.values(data).filter(v => v !== undefined), + ) + return meanOfAnsweredQuestions * 12 + } + + const fjsScore = 100 - ((getWipScore() - 12) / 48) * 100 + + return { FORGOTTEN_JOINT_SCORE_KNEE: Math.round(fjsScore) } + }, +} diff --git a/todo/ghq_12/README.md b/src/scores/ghq_12/README.md similarity index 100% rename from todo/ghq_12/README.md rename to src/scores/ghq_12/README.md diff --git a/todo/ghq_12/__testdata__/ghq_12_test_responses.ts b/src/scores/ghq_12/__testdata__/ghq_12_test_responses.ts similarity index 100% rename from todo/ghq_12/__testdata__/ghq_12_test_responses.ts rename to src/scores/ghq_12/__testdata__/ghq_12_test_responses.ts diff --git a/todo/ghq_12/definition/ghq_12_inputs.ts b/src/scores/ghq_12/definition/ghq_12_inputs.ts similarity index 85% rename from todo/ghq_12/definition/ghq_12_inputs.ts rename to src/scores/ghq_12/definition/ghq_12_inputs.ts index 295f8ca..c54b87b 100644 --- a/todo/ghq_12/definition/ghq_12_inputs.ts +++ b/src/scores/ghq_12/definition/ghq_12_inputs.ts @@ -1,15 +1,15 @@ -import type { InputType } from '../../../src/types/calculations.types' +import { z } from 'zod' +import { ScoreInputSchemaType } from '../../../types' -export const GHQ_12_INPUTS: Array = [ - { - input_id: 'GHQ_12_Q01', +export const GHQ_12_INPUTS = { + GHQ_12_Q01: { label: { nl: 'Hebt u zich in de afgelopen weken kunnen concentreren op uw bezigheden?', en: 'Over the past few weeks... Have you been able to concentrate well on what you were doing?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Beter dan gewoonlijk', en: 'Better than usual' }, @@ -37,17 +37,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q02', + GHQ_12_Q02: { label: { nl: 'Bent u in de afgelopen weken door zorgen veel slaap tekort gekomen?', en: 'Over the past few weeks... Have your worries made you lose a lot of sleep?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Helemaal niet', en: 'Not at all' }, @@ -75,17 +73,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q03', + GHQ_12_Q03: { label: { nl: 'Hebt u in de afgelopen weken het gevoel gehad zinvol bezig te zijn?', en: 'Over the past few weeks... Have you felt that you are playing a useful role in life?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Meer dan gewoonlijk', en: 'More so than usual' }, @@ -113,17 +109,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q04', + GHQ_12_Q04: { label: { nl: 'Voelde u zich in de afgelopen weken in staat om beslissingen (over dingen) te nemen?', en: 'Over the past few weeks... Have you felt capable of making decisions?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Meer dan gewoonlijk', en: 'More so than usual' }, @@ -151,17 +145,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q05', + GHQ_12_Q05: { label: { nl: 'Hebt u in de afgelopen weken het gevoel gehad dat u voortdurend onder druk stond?', en: 'Over the past few weeks... Have you felt constantly overwhelmed and stressed?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Helemaal niet', en: 'Not at all' }, @@ -189,17 +181,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q06', + GHQ_12_Q06: { label: { nl: 'Hebt u in de afgelopen weken het gevoel gehad dat u uw moeilijkheden niet de baas kon?', en: 'Over the past few weeks... Have you had the feeling that you cannot overcome your difficulties?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Helemaal niet', en: 'Not at all' }, @@ -227,17 +217,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q07', + GHQ_12_Q07: { label: { nl: 'Hebt u in de afgelopen weken plezier kunnen beleven aan uw gewone, dagelijkse bezigheden?', en: 'Over the past few weeks... Have you been able to enjoy your normal daily activities?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Meer dan gewoonlijk', en: 'More so than usual' }, @@ -265,17 +253,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q08', + GHQ_12_Q08: { label: { nl: 'Bent u in de afgelopen weken in staat geweest uw problemen onder ogen te zien?', en: 'Over the past few weeks... Have you been able to adequately cope with your problems?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Beter dan gewoonlijk', en: 'More so than usual' }, @@ -303,17 +289,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q09', + GHQ_12_Q09: { label: { nl: 'Hebt u zich in de afgelopen weken ongelukkig of neerslachtig gevoeld?', en: 'Over the past few weeks... Have you felt unhappy or depressed?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Helemaal niet', en: 'Not at all' }, @@ -341,17 +325,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q10', + GHQ_12_Q10: { label: { nl: 'Bent u in de afgelopen weken het vertrouwen in uzelf kwijtgeraakt?', en: 'Over the past few weeks... Have you lost confidence in yourself?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Helemaal niet', en: 'Not at all' }, @@ -379,17 +361,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q11', + GHQ_12_Q11: { label: { nl: 'Hebt u zich in de afgelopen weken als een waardeloos iemand beschouwd?', en: 'Over the past few weeks... Have you thought that you are a person worthless?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Helemaal niet', en: 'Not at all' }, @@ -417,17 +397,15 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, - { - input_id: 'GHQ_12_Q12', + GHQ_12_Q12: { label: { nl: 'Hebt u zich in de afgelopen weken alles bij elkaar redelijk gelukkig gevoeld?', en: 'Over the past few weeks... Do you feel reasonably happy considering all the circumstances?', }, - type: { - type: 'number', - allowed_answers: [ + type: z.union([z.literal(0), z.literal(1), z.literal(2), z.literal(3)]), + uiOptions: { + options: [ { value: 0, label: { nl: 'Beter dan gewoonlijk', en: 'More so than usual' }, @@ -455,6 +433,5 @@ export const GHQ_12_INPUTS: Array = [ }, ], }, - required: true, }, -] +} satisfies ScoreInputSchemaType diff --git a/src/scores/ghq_12/definition/ghq_12_output.ts b/src/scores/ghq_12/definition/ghq_12_output.ts new file mode 100644 index 0000000..b115ac8 --- /dev/null +++ b/src/scores/ghq_12/definition/ghq_12_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const GHQ_12_OUTPUT = { + GHQ_12_SCORING: { + label: { en: 'GHQ Scoring' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/ghq_12/definition/index.ts b/src/scores/ghq_12/definition/index.ts similarity index 100% rename from todo/ghq_12/definition/index.ts rename to src/scores/ghq_12/definition/index.ts diff --git a/src/scores/ghq_12/ghq_12.test.ts b/src/scores/ghq_12/ghq_12.test.ts new file mode 100644 index 0000000..118d634 --- /dev/null +++ b/src/scores/ghq_12/ghq_12.test.ts @@ -0,0 +1,150 @@ +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' +import { + best_response, + median_response, + random_response, + worst_response, +} from './__testdata__/ghq_12_test_responses' +import { ghq_12 } from './ghq_12' + +const GHQ_12_BEST_SCORE = 0 +const GHQ_12_MEDIAN_SCORE = 6 +const GHQ_12_WORST_SCORE = 12 + +const ghq_12_calculation = new Score(ghq_12) + +describe('ghq_12', function () { + it('ghq_12 calculation function should be available as a calculation', function () { + expect(ScoreLibrary).toHaveProperty('ghq_12') + }) + + describe('basic assumptions', function () { + const outcome = ghq_12_calculation.calculate({ payload: best_response }) + + it('should return 1 calculation result', function () { + expect(Object.keys(outcome).length).toEqual(1) + }) + + it('should have the expected calculation id', function () { + const EXPECTED_CALCULATION_ID = ['GHQ_12_SCORING'] + 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 = [ + 'GHQ_12_Q01', + 'GHQ_12_Q02', + 'GHQ_12_Q03', + 'GHQ_12_Q04', + 'GHQ_12_Q05', + 'GHQ_12_Q06', + 'GHQ_12_Q07', + 'GHQ_12_Q08', + 'GHQ_12_Q09', + 'GHQ_12_Q10', + 'GHQ_12_Q11', + 'GHQ_12_Q12', + ] + + const configured_input_ids = Object.keys(ghq_12_calculation.inputSchema) + + expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) + }) + }) + + describe('when an answer is below the expected range', function () { + it('should throw an ZodError', function () { + expect(() => + ghq_12_calculation.calculate({ + payload: { + GHQ_12_Q01: -1, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when an answer is above the expected range', function () { + it('should throw an ZodError', function () { + expect(() => + ghq_12_calculation.calculate({ + payload: { + GHQ_12_Q01: 4, + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when there are non-numerical answers', function () { + it('should throw an ZodError', function () { + expect(() => + ghq_12_calculation.calculate({ + payload: { + GHQ_12_Q01: "I'm not a number", + }, + }), + ).toThrow(ZodError) + }) + }) + + describe('when called with an empty response', function () { + it('should throw a ZodError', function () { + expect(() => ghq_12_calculation.calculate({ payload: {} })).toThrow( + ZodError, + ) + }) + }) + }) + + describe('score calculation', function () { + describe('when called with the worst response', function () { + it('should return the worst score', function () { + const score = ghq_12_calculation.calculate({ + payload: worst_response, + }) + + expect(score.GHQ_12_SCORING).toEqual(GHQ_12_WORST_SCORE) + }) + }) + + describe('when called with a median response', function () { + it('should return the median score', function () { + const score = ghq_12_calculation.calculate({ + payload: median_response, + }) + + expect(score.GHQ_12_SCORING).toEqual(GHQ_12_MEDIAN_SCORE) + }) + }) + + describe('when called with a maximum response', function () { + it('should return the maximum score', function () { + const score = ghq_12_calculation.calculate({ + payload: best_response, + }) + + expect(score.GHQ_12_SCORING).toEqual(GHQ_12_BEST_SCORE) + }) + }) + + describe('when called with a random response', function () { + it('should return the expected score', function () { + const score = ghq_12_calculation.calculate({ + payload: random_response, + }) + + const EXPECTED_SCORE = 9 + + expect(score.GHQ_12_SCORING).toEqual(EXPECTED_SCORE) + }) + }) + }) +}) diff --git a/src/scores/ghq_12/ghq_12.ts b/src/scores/ghq_12/ghq_12.ts new file mode 100644 index 0000000..f54ab47 --- /dev/null +++ b/src/scores/ghq_12/ghq_12.ts @@ -0,0 +1,21 @@ +import { GHQ_12_INPUTS, GHQ_12_OUTPUT } from './definition' +import { ScoreType } from '../../types' + +export const ghq_12: ScoreType = { + name: 'The 12-Item General Health Questionnaire (GHQ-12)', + readmeLocation: __dirname, + inputSchema: GHQ_12_INPUTS, + outputSchema: GHQ_12_OUTPUT, + calculate: ({ data }) => { + /** + * GHQ score is the sum of the amount of items that were scored 2 or 3 + */ + const DYSFUNCTIONAL_SCORES = [2, 3] + + const score = Object.values(data).filter(val => + DYSFUNCTIONAL_SCORES.includes(val), + ).length + + return { GHQ_12_SCORING: score } + }, +} diff --git a/src/scores/hoos_ps/hoos_ps.test.ts b/src/scores/hoos_ps/hoos_ps.test.ts index 40e241b..2107540 100644 --- a/src/scores/hoos_ps/hoos_ps.test.ts +++ b/src/scores/hoos_ps/hoos_ps.test.ts @@ -104,7 +104,7 @@ describe('hoos_ps', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hoos_ps_calculation.calculate({ payload: { @@ -115,7 +115,7 @@ describe('hoos_ps', function () { }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hoos_ps_calculation.calculate({ payload: { @@ -126,7 +126,7 @@ describe('hoos_ps', function () { }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hoos_ps_calculation.calculate({ payload: { diff --git a/src/scores/hoos_ps/hoos_ps.ts b/src/scores/hoos_ps/hoos_ps.ts index 31fdc39..464cfb3 100644 --- a/src/scores/hoos_ps/hoos_ps.ts +++ b/src/scores/hoos_ps/hoos_ps.ts @@ -4,7 +4,7 @@ import { hoos_conversion_table, } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const hoos_ps: ScoreType = { @@ -13,7 +13,7 @@ export const hoos_ps: ScoreType = inputSchema: HOOS_PS_INPUTS, outputSchema: HOOS_PS_OUTPUT, calculate: ({ data }) => { - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) return { HOOS_PS: hoos_conversion_table[totalScore.toString()], } diff --git a/todo/ibd_disk_total_score/README.md b/src/scores/ibd_disk_total_score/README.md similarity index 100% rename from todo/ibd_disk_total_score/README.md rename to src/scores/ibd_disk_total_score/README.md diff --git a/todo/ibd_disk_total_score/__testdata__/IBD_disk_responses.ts b/src/scores/ibd_disk_total_score/__testdata__/IBD_disk_responses.ts similarity index 100% rename from todo/ibd_disk_total_score/__testdata__/IBD_disk_responses.ts rename to src/scores/ibd_disk_total_score/__testdata__/IBD_disk_responses.ts diff --git a/todo/ibd_disk_total_score/definition/ibd_disk_inputs.ts b/src/scores/ibd_disk_total_score/definition/ibd_disk_inputs.ts similarity index 75% rename from todo/ibd_disk_total_score/definition/ibd_disk_inputs.ts rename to src/scores/ibd_disk_total_score/definition/ibd_disk_inputs.ts index 301adff..4751274 100644 --- a/todo/ibd_disk_total_score/definition/ibd_disk_inputs.ts +++ b/src/scores/ibd_disk_total_score/definition/ibd_disk_inputs.ts @@ -1,110 +1,90 @@ -import type { InputType } from '../../../src/types/calculations.types' -import { NumberInputType } from '../../../src/types/calculations/inputs/calculation-inputs.types' +import { z } from 'zod' +import { ScoreInputSchemaType, SimpleNumberInputType } from '../../../types' -const type: NumberInputType = { - type: 'number', - component: 'slider', - range: { - min: { - value: 0, - label: { en: 'Absolutely disagree', nl: 'Helemaal niet akkoord' }, - }, - max: { - value: 10, - label: { en: 'Absolutely agree', nl: 'Helemaal akkoord' }, +const type = { + type: z.number(), + uiOptions: { + component: 'slider', + range: { + min: { + label: { en: 'Absolutely disagree', nl: 'Helemaal niet akkoord' }, + }, + max: { + label: { en: 'Absolutely agree', nl: 'Helemaal akkoord' }, + }, }, }, -} +} satisfies SimpleNumberInputType -export const IBD_DISK_INPUTS: Array = [ - { - input_id: 'abdominal_pain', +export const IBD_DISK_INPUTS = { + abdominal_pain: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa last van pijn ter hoogte van mijn maag of buik.', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had aches or pains in my stomach or abdomen.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'regulating_defecation', + regulating_defecation: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa moeilijkheden met het regelen van mijn stoelgang, met inbegrip van het zoeken naar een nabijgelegen toilet en de reiniging nadien.', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had difficulty coordinating and managing defecation, including choosing and getting to an appropriate place for defecation and cleaning myself afterwards.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'interpersonal_interactions', + interpersonal_interactions: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa moeilijkheden met persoonlijke relaties/sociale contacten en/of deelname aan publieke activiteiten (interpersoonlijke interacties).', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had difficulty with personal relationships and/or difficulty participating in the community.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'education_and_work', + education_and_work: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa moeilijkheden met school of studeren, en/of moeilijkheden met het werk of huishoudelijke activiteiten (educatie en werk).', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had difficulty with school or studying activities, and/or difficulty with work or household activities.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'sleep', + sleep: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa slaapproblemen, zoals moeilijk inslapen, frequent wakker worden ’s nachts of te vroeg wakker worden ’s ochtends.', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had difficulty sleeping, such as falling asleep, waking up frequently during the night or waking up too early in the morning.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'energy', + energy: { label: { nl: 'Tijdens de laatste week voelde ik me, omwille van mijn ziekte van Crohn of colitis ulcerosa, niet uitgerust gedurende de dag. Ik voelde mij moe en futloos.', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have not felt rested and refreshed during the day, and have felt tired and without energy.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'emotions', + emotions: { label: { nl: 'Tijdens de laatste week voelde ik me, omwille van mijn ziekte van Crohn of colitis ulcerosa, verdrietig, depressief en/of bezorgd of angstig.', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have felt sad, low or depressed, and/or worried or anxious.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'body_image', + body_image: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa was ik niet tevreden met mijn uiterlijk of een deel hiervan (lichaamsbeeld).', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have not liked the way my body or body parts look.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'sexual_function', + sexual_function: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa problemen met de fysieke of mentale aspecten van seks (sexuele functie).', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had difficulty with the mental and/or physical aspects of sex.", }, - input_type, - required: true, + ...type, }, - { - input_id: 'arthralgia', + arthralgia: { label: { nl: 'Tijdens de laatste week had ik omwille van mijn ziekte van Crohn of colitis ulcerosa pijn ter hoogte van mijn gewrichten.', en: "In the past week, because of my Crohn's disease or ulcerative colitis I have had pains in the joints of my body.", }, - input_type, - required: true, + ...type, }, -] +} satisfies ScoreInputSchemaType diff --git a/src/scores/ibd_disk_total_score/definition/ibd_disk_output.ts b/src/scores/ibd_disk_total_score/definition/ibd_disk_output.ts new file mode 100644 index 0000000..33af737 --- /dev/null +++ b/src/scores/ibd_disk_total_score/definition/ibd_disk_output.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' +import { ScoreOutputSchemaType } from '../../../types' + +export const IBD_DISK_OUTPUT = { + IBD_DISK_TOTAL: { + label: { en: 'IBD Disk total' }, + type: z.number(), + }, +} satisfies ScoreOutputSchemaType diff --git a/todo/ibd_disk_total_score/definition/index.ts b/src/scores/ibd_disk_total_score/definition/index.ts similarity index 100% rename from todo/ibd_disk_total_score/definition/index.ts rename to src/scores/ibd_disk_total_score/definition/index.ts diff --git a/todo/ibd_disk_total_score/ibd_disk_total_score.test.ts b/src/scores/ibd_disk_total_score/ibd_disk_total_score.test.ts similarity index 52% rename from todo/ibd_disk_total_score/ibd_disk_total_score.test.ts rename to src/scores/ibd_disk_total_score/ibd_disk_total_score.test.ts index 2f81380..9545e9a 100644 --- a/todo/ibd_disk_total_score/ibd_disk_total_score.test.ts +++ b/src/scores/ibd_disk_total_score/ibd_disk_total_score.test.ts @@ -1,29 +1,23 @@ -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 { CALCULATIONS } from '../calculation_library' -import { get_input_ids_from_calculation_blueprint } from '../shared_functions' +import { ZodError } from 'zod' +import { Score } from '../../classes' +import { ScoreLibrary } from '../library' import { max_response, median_response, min_response, random_response, } from './__testdata__/IBD_disk_responses' -import { IBD_DISK_INPUTS } from './definition/ibd_disk_inputs' import { ibd_disk_total_score } from './ibd_disk_total_score' const IBD_DISK_MIN_SCORE = 0 const IBD_DISK_MEDIAN_SCORE = 50 const IBD_DISK_MAX_SCORE = 100 -const ibd_disk_calculation = execute_test_calculation(ibd_disk_total_score) +const ibd_disk_calculation = new Score(ibd_disk_total_score) describe('ibd_disk_total_score', function () { it('ibd_disk_total_score calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('ibd_disk_total_score') + expect(ScoreLibrary).toHaveProperty('ibd_disk_total_score') }) describe('the score includes the correct input fields', function () { @@ -41,25 +35,25 @@ describe('ibd_disk_total_score', function () { 'arthralgia', ] - const configured_calculation_input_ids = - get_input_ids_from_calculation_blueprint(IBD_DISK_INPUTS) + const configured_calculation_input_ids = Object.keys( + ibd_disk_calculation.inputSchema, + ) - expect(configured_calculation_input_ids).to.have.members( + expect(configured_calculation_input_ids).toEqual( EXPECTED_CALCULATION_INPUT_IDS, ) }) }) describe('each calculated score includes the correct output result and correct score title', function () { - const outcome = ibd_disk_calculation(min_response) + const outcome = ibd_disk_calculation.calculate({ payload: min_response }) it('should calculate a single score', function () { - expect(outcome).toHaveLength(1) + expect(Object.keys(outcome).length).toEqual(1) }) it('should have the correct calculation id', function () { - const configured_calculation_id = - get_result_ids_from_calculation_output(outcome) + const configured_calculation_id = Object.keys(outcome) expect(configured_calculation_id).toEqual(['IBD_DISK_TOTAL']) }) @@ -68,28 +62,28 @@ describe('ibd_disk_total_score', function () { describe('each calculated score includes the correct formula and outputs the correct result', function () { describe('when a minimum response is passed', function () { it('should return the minimum score', function () { - const outcome = ibd_disk_calculation(min_response) - const result = view_result()(outcome) - - expect(result).toEqual(IBD_DISK_MIN_SCORE) + const outcome = ibd_disk_calculation.calculate({ + payload: min_response, + }) + expect(outcome.IBD_DISK_TOTAL).toEqual(IBD_DISK_MIN_SCORE) }) }) describe('when a median response is passed', function () { it('should return the median score', function () { - const outcome = ibd_disk_calculation(median_response) - const result = view_result()(outcome) - - expect(result).toEqual(IBD_DISK_MEDIAN_SCORE) + const outcome = ibd_disk_calculation.calculate({ + payload: median_response, + }) + expect(outcome.IBD_DISK_TOTAL).toEqual(IBD_DISK_MEDIAN_SCORE) }) }) describe('when a maximum response is passed', function () { it('should return the maximum score', function () { - const outcome = ibd_disk_calculation(max_response) - const result = view_result()(outcome) - - expect(result).toEqual(IBD_DISK_MAX_SCORE) + const outcome = ibd_disk_calculation.calculate({ + payload: max_response, + }) + expect(outcome.IBD_DISK_TOTAL).toEqual(IBD_DISK_MAX_SCORE) }) }) @@ -97,51 +91,56 @@ describe('ibd_disk_total_score', function () { it('should return the expected score', function () { const EXPECTED_SCORE = 44 - const outcome = ibd_disk_calculation(random_response) - const result = view_result()(outcome) - - expect(result).toEqual(EXPECTED_SCORE) + const outcome = ibd_disk_calculation.calculate({ + payload: random_response, + }) + expect(outcome.IBD_DISK_TOTAL).toEqual(EXPECTED_SCORE) }) }) }) describe('a score is only calculated when all mandatory fields are entered', function () { describe('when an empty response is passed', function () { - it('should return undefined as the result', function () { - const outcome = ibd_disk_calculation({}) - const result = view_result()(outcome) - - expect(result).toEqual(undefined) + it('should throw a ZodError', function () { + expect(() => ibd_disk_calculation.calculate({ payload: {} })).toThrow( + ZodError, + ) }) }) }) describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => - ibd_disk_calculation({ - abdominal_pain: "I'm not a number", + ibd_disk_calculation.calculate({ + payload: { + abdominal_pain: "I'm not a number", + }, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0, 5] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => - ibd_disk_calculation({ - abdominal_pain: -1, + ibd_disk_calculation.calculate({ + payload: { + abdominal_pain: -1, + }, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0, 5] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => - ibd_disk_calculation({ - abdominal_pain: 11, + ibd_disk_calculation.calculate({ + payload: { + abdominal_pain: 11, + }, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/src/scores/ibd_disk_total_score/ibd_disk_total_score.ts b/src/scores/ibd_disk_total_score/ibd_disk_total_score.ts new file mode 100644 index 0000000..ba4f98c --- /dev/null +++ b/src/scores/ibd_disk_total_score/ibd_disk_total_score.ts @@ -0,0 +1,18 @@ +import { IBD_DISK_INPUTS, IBD_DISK_OUTPUT } from './definition' +import { ScoreType } from '../../types' +import { sum } from 'lodash' + +export const ibd_disk_total_score: ScoreType< + typeof IBD_DISK_INPUTS, + typeof IBD_DISK_OUTPUT +> = { + name: 'IBD Disk total score', + readmeLocation: __dirname, + inputSchema: IBD_DISK_INPUTS, + outputSchema: IBD_DISK_OUTPUT, + calculate: ({ data }) => { + return { + IBD_DISK_TOTAL: sum(Object.values(data)), + } + }, +} diff --git a/src/scores/koos_ps/koos_ps.test.ts b/src/scores/koos_ps/koos_ps.test.ts index faad161..ac86fe1 100644 --- a/src/scores/koos_ps/koos_ps.test.ts +++ b/src/scores/koos_ps/koos_ps.test.ts @@ -110,7 +110,7 @@ describe('koos_ps', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => koos_ps_calculation.calculate({ payload: { @@ -121,7 +121,7 @@ describe('koos_ps', function () { }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => koos_ps_calculation.calculate({ payload: { @@ -132,7 +132,7 @@ describe('koos_ps', function () { }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => koos_ps_calculation.calculate({ payload: { diff --git a/src/scores/koos_ps/koos_ps.ts b/src/scores/koos_ps/koos_ps.ts index 9c5c1c7..3a8b2f1 100644 --- a/src/scores/koos_ps/koos_ps.ts +++ b/src/scores/koos_ps/koos_ps.ts @@ -4,7 +4,7 @@ import { koos_conversion_table, } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const koos_ps: ScoreType = { @@ -13,7 +13,7 @@ export const koos_ps: ScoreType = inputSchema: KOOS_PS_INPUTS, outputSchema: KOOS_PS_OUTPUT, calculate: ({ data }) => { - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) return { KOOS_PS: koos_conversion_table[totalScore.toString()], } diff --git a/src/scores/library.test.ts b/src/scores/library.test.ts index 03b3018..897b3e5 100644 --- a/src/scores/library.test.ts +++ b/src/scores/library.test.ts @@ -1,5 +1,3 @@ -import R from 'ramda' - import { ScoreLibrary } from './library' describe('calculation library', function () { diff --git a/src/scores/library.ts b/src/scores/library.ts index 21d6fa3..3bbd0ce 100644 --- a/src/scores/library.ts +++ b/src/scores/library.ts @@ -8,17 +8,17 @@ import { bwcs } from './bwcs/bwcs' import { bmi_metric, bmi_imperial } from './bmi' // import { breast_q as breast_q_conserving_therapy_pre_and_postoperative } from './breast_q/breast_conserving/breast_q' // import { cade_q_sv } from './cade_q' -// import { caregiver_strain_index } from './caregiver_strain_index/caregiver_strain_index' +import { caregiver_strain_index } from './caregiver_strain_index/caregiver_strain_index' // import { cat } from './cat/cat' // import { ccq } from './ccq/ccq' // import { cdlqi } from './cdlqi/cdlqi' -// import { CHA2DS2_VASc_Score } from './CHA2DS2_VASc_Score/CHA2DS2_VASc_Score' +import { CHA2DS2_VASc_Score } from './CHA2DS2_VASc_Score/CHA2DS2_VASc_Score' // import { chc_preop_brochure_triage } from './chc' // import { femmes_enceintes_triage } from './chc/femmes_enceintes/triage/triage' // import { comi_back, comi_neck } from './comi' // import { compass_31 } from './compass_31/compass_31' // import { constant_murley_score_orthotoolkit } from './constant_murley_score' -// import { core_om } from './core_om/core_om' +import { core_om } from './core_om/core_om' import { cpdi } from './cpdi/cpdi' // import { csi } from './csi/csi' import { dast_10 } from './dast_10/dast_10' @@ -38,20 +38,20 @@ import { dn4 } from './dn4/dn4' // } from './eortc' // import { epic_26 } from './epic_26/epic_26' import { eq5d_3l, eq5d_5l } from './eq5d' -// import { ess } from './ess/ess' +import { ess } from './ess/ess' // import { faam } from './faam/faam' // import { short_fes_i } from './fes_i' import { fnd } from './fnd/fnd' // import { foot_function_index_5pt } from './foot_function_index' -// import { -// forgotten_joint_score_hip, -// forgotten_joint_score_knee, -// } from './forgotten_joint_score_12' +import { + forgotten_joint_score_hip, + forgotten_joint_score_knee, +} 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 { ghq_12 } from './ghq_12/ghq_12' +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' // import { hoos_extended } from './hoos_extended/hoos_extended' @@ -59,8 +59,8 @@ import { hoos_ps } from './hoos_ps/hoos_ps' // import { hos } from './hos/hos' // import { hrqol_4 } from './hrqol' // import { ias } from './ias/ias' -// import { IBD_control } from './IBD_control/IBD_control' -// import { ibd_disk_total_score } from './ibd_disk_total_score/ibd_disk_total_score' +import { IBD_control } from './IBD_control/IBD_control' +import { ibd_disk_total_score } from './ibd_disk_total_score/ibd_disk_total_score' // import { iief5 } from './iief5/iief5' // import { ikdc } from './ikdc/ikdc' // import { ipss } from './ipss/ipss' @@ -119,7 +119,6 @@ import { yp_core } from './yp_core/yp_core' // import { zarit_12 } from './zarit_12/zarit_12' import { acro } from './acro/acro' import { Score } from '../classes' -import _ from 'lodash' import { ScoreType } from '../types' // import { korq } from './korq/korq' // import { mlks } from './mlks/mlks' @@ -152,18 +151,18 @@ export const ScoreLibrary = createScoreLibrary({ bwcs, // breast_q_conserving_therapy_pre_and_postoperative, // cade_q_sv, - // caregiver_strain_index, + caregiver_strain_index, // cat, // ccq, // cdlqi, - // CHA2DS2_VASc_Score, + CHA2DS2_VASc_Score, // chc_preop_brochure_triage, // femmes_enceintes_triage, // comi_back, // comi_neck, // compass_31, // constant_murley_score_orthotoolkit, - // core_om, + core_om, cpdi, // csi, dast_10, @@ -182,15 +181,15 @@ export const ScoreLibrary = createScoreLibrary({ // epic_26, eq5d_3l, eq5d_5l, - // ess, + ess, // faam, fnd, // foot_function_index_5pt, - // forgotten_joint_score_hip, - // forgotten_joint_score_knee, + forgotten_joint_score_hip, + forgotten_joint_score_knee, gad_2, gad_7, - // ghq_12, + ghq_12, // hads, // harris_hip_score, // hoos_extended, @@ -198,8 +197,8 @@ export const ScoreLibrary = createScoreLibrary({ // hos, // hrqol_4, // ias, - // IBD_control, - // ibd_disk_total_score, + IBD_control, + ibd_disk_total_score, // iief5, // ikdc, // isi, diff --git a/src/scores/packyears/packyears.test.ts b/src/scores/packyears/packyears.test.ts index 4405776..bba0640 100644 --- a/src/scores/packyears/packyears.test.ts +++ b/src/scores/packyears/packyears.test.ts @@ -75,7 +75,7 @@ describe('packyears', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => packyears_calculation.calculate({ payload: { @@ -86,7 +86,7 @@ describe('packyears', function () { }) }) describe('when an answer is below the expected [0, 4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => packyears_calculation.calculate({ payload: { @@ -97,7 +97,7 @@ describe('packyears', function () { }) }) describe('when an answer is above the expected [0, 4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => packyears_calculation.calculate({ payload: { diff --git a/src/scores/packyears/packyears.ts b/src/scores/packyears/packyears.ts index 9343f3f..3ea8efc 100644 --- a/src/scores/packyears/packyears.ts +++ b/src/scores/packyears/packyears.ts @@ -1,6 +1,5 @@ import { PACKYEARS_INPUTS, PACKYEARS_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' export const packyears: ScoreType< typeof PACKYEARS_INPUTS, diff --git a/src/scores/panss_6/panss_6.test.ts b/src/scores/panss_6/panss_6.test.ts index 611c605..def2098 100644 --- a/src/scores/panss_6/panss_6.test.ts +++ b/src/scores/panss_6/panss_6.test.ts @@ -50,7 +50,7 @@ describe('panss_6', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => panss_6_calculation.calculate({ payload: { @@ -62,7 +62,7 @@ describe('panss_6', function () { }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => panss_6_calculation.calculate({ payload: { @@ -74,7 +74,7 @@ describe('panss_6', function () { }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => panss_6_calculation.calculate({ payload: { diff --git a/src/scores/panss_6/panss_6.ts b/src/scores/panss_6/panss_6.ts index d7ddb87..7727b72 100644 --- a/src/scores/panss_6/panss_6.ts +++ b/src/scores/panss_6/panss_6.ts @@ -1,7 +1,6 @@ import { PANSS_6_INPUTS, PANNS_6_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' - +import { sum } from 'lodash' export const panss_6: ScoreType = { name: 'Positive and Negative Syndrome Scale (PANSS-6)', @@ -21,8 +20,8 @@ export const panss_6: ScoreType = data.PANSS_6_Q06_LACK_OF_SPONTANEITY, ] - const positiveScaleScore = _.sum(positiveScaleScores) - const negativeScaleScore = _.sum(negativeScaleScores) + const positiveScaleScore = sum(positiveScaleScores) + const negativeScaleScore = sum(negativeScaleScores) return { PANNS_6_POSITIVE_SCALE_SCORE: positiveScaleScore, diff --git a/src/scores/pdq_8/pdq_8.test.ts b/src/scores/pdq_8/pdq_8.test.ts index d46709c..3c06c45 100644 --- a/src/scores/pdq_8/pdq_8.test.ts +++ b/src/scores/pdq_8/pdq_8.test.ts @@ -110,7 +110,7 @@ describe('pdq_8', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pdq8_calculation.calculate({ payload: { @@ -121,7 +121,7 @@ describe('pdq_8', function () { }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pdq8_calculation.calculate({ payload: { @@ -132,7 +132,7 @@ describe('pdq_8', function () { }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pdq8_calculation.calculate({ payload: { diff --git a/src/scores/pdq_8/pdq_8.ts b/src/scores/pdq_8/pdq_8.ts index 50494c6..7304927 100644 --- a/src/scores/pdq_8/pdq_8.ts +++ b/src/scores/pdq_8/pdq_8.ts @@ -1,6 +1,6 @@ import { PDQ_8_INPUTS, PDQ_8_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const pdq_8: ScoreType = { name: "Parkinson's Disease Questionnaire-8 (PDQ-8)", @@ -9,7 +9,7 @@ export const pdq_8: ScoreType = { outputSchema: PDQ_8_OUTPUT, calculate: ({ data }) => { const MAX_SCORE = 32 - const score = _.sum(Object.values(data)) + const score = sum(Object.values(data)) const percentage = (score / MAX_SCORE) * 100 return { diff --git a/src/scores/phq_2/phq_2.test.ts b/src/scores/phq_2/phq_2.test.ts index 461b209..3b01678 100644 --- a/src/scores/phq_2/phq_2.test.ts +++ b/src/scores/phq_2/phq_2.test.ts @@ -50,7 +50,7 @@ describe('phq_2', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => phq_2_calculation.calculate({ payload: { diff --git a/src/scores/phq_2/phq_2.ts b/src/scores/phq_2/phq_2.ts index 0c9314c..29077dd 100644 --- a/src/scores/phq_2/phq_2.ts +++ b/src/scores/phq_2/phq_2.ts @@ -1,6 +1,5 @@ import { PHQ2_INPUTS, PHQ2_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' export const phq_2: ScoreType = { name: 'Patient Health Questionnaire-2 (PHQ-2)', diff --git a/src/scores/phq_4/phq_4.test.ts b/src/scores/phq_4/phq_4.test.ts index cc3008b..8ca6210 100644 --- a/src/scores/phq_4/phq_4.test.ts +++ b/src/scores/phq_4/phq_4.test.ts @@ -58,7 +58,7 @@ describe('phq_4', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => phq_4_calculation.calculate({ payload: { diff --git a/src/scores/phq_4/phq_4.ts b/src/scores/phq_4/phq_4.ts index 6b68889..2927916 100644 --- a/src/scores/phq_4/phq_4.ts +++ b/src/scores/phq_4/phq_4.ts @@ -1,6 +1,5 @@ import { PHQ4_INPUTS, PHQ4_OUTPUT, PHQ4_INTERPRATION_TABLE } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' export const phq_4: ScoreType = { name: 'Patient Health Questionnaire-4 (PHQ-4)', diff --git a/src/scores/phq_8/phq_8.test.ts b/src/scores/phq_8/phq_8.test.ts index 5055d02..33d3811 100644 --- a/src/scores/phq_8/phq_8.test.ts +++ b/src/scores/phq_8/phq_8.test.ts @@ -57,7 +57,7 @@ describe('phq_8', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => phq_8_calculation.calculate({ payload: { diff --git a/src/scores/phq_8/phq_8.ts b/src/scores/phq_8/phq_8.ts index 801112f..b1476bb 100644 --- a/src/scores/phq_8/phq_8.ts +++ b/src/scores/phq_8/phq_8.ts @@ -1,6 +1,6 @@ import { PHQ8_INPUTS, PHQ8_OUTPUT, PHQ8_INTERPRATION_TABLE } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const phq_8: ScoreType = { name: 'Patient Health Questionnaire-8 (PHQ-8)', @@ -8,7 +8,7 @@ export const phq_8: ScoreType = { inputSchema: PHQ8_INPUTS, outputSchema: PHQ8_OUTPUT, calculate: ({ data }) => { - const total_score = _.sum(Object.values(data)) + const total_score = sum(Object.values(data)) return { PHQ8_SCORE: total_score, diff --git a/src/scores/phq_9/phq_9.test.ts b/src/scores/phq_9/phq_9.test.ts index 63bd802..420a662 100644 --- a/src/scores/phq_9/phq_9.test.ts +++ b/src/scores/phq_9/phq_9.test.ts @@ -58,7 +58,7 @@ describe('phq_9', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => phq_9_calculation.calculate({ payload: { diff --git a/src/scores/phq_9/phq_9.ts b/src/scores/phq_9/phq_9.ts index fbfbfd5..46cc18b 100644 --- a/src/scores/phq_9/phq_9.ts +++ b/src/scores/phq_9/phq_9.ts @@ -1,6 +1,6 @@ import { PHQ9_INPUTS, PHQ9_OUTPUT, PHQ9_INTERPRATION_TABLE } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const phq_9: ScoreType = { name: 'Patient Health Questionnaire-9 (PHQ-9)', @@ -8,7 +8,7 @@ export const phq_9: ScoreType = { inputSchema: PHQ9_INPUTS, outputSchema: PHQ9_OUTPUT, calculate: ({ data }) => { - const total_score = _.sum(Object.values(data)) + const total_score = sum(Object.values(data)) return { PHQ9_SCORE: total_score, diff --git a/src/scores/pro2/pro2.ts b/src/scores/pro2/pro2.ts index 81a9f6c..3b57bc4 100644 --- a/src/scores/pro2/pro2.ts +++ b/src/scores/pro2/pro2.ts @@ -1,6 +1,6 @@ import { PRO2_INPUTS, PRO2_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum, omit } from 'lodash' import { GENERAL_WELL_BEING_FACTOR, STOOL_FREQUENCY_FACTOR, @@ -18,12 +18,12 @@ export const pro2: ScoreType = { const weightedGeneralWellBeing = data.GENERAL_WELL_BEING * GENERAL_WELL_BEING_FACTOR - const totalScore = _.sum([ + const totalScore = sum([ weightedAbdominalPain, weightedStoolFrequency, weightedGeneralWellBeing, ...Object.values( - _.omit(data, [ + omit(data, [ // We use the weighted values for the total score 'STOOL_FREQUENCY', 'ABDOMINAL_PAIN', diff --git a/src/scores/pss_4/pss_4.test.ts b/src/scores/pss_4/pss_4.test.ts index a64230f..996627d 100644 --- a/src/scores/pss_4/pss_4.test.ts +++ b/src/scores/pss_4/pss_4.test.ts @@ -49,7 +49,7 @@ describe('pss_4', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pss_4_calculation.calculate({ payload: { diff --git a/src/scores/pss_4/pss_4.ts b/src/scores/pss_4/pss_4.ts index 6ae62e3..4de2bd4 100644 --- a/src/scores/pss_4/pss_4.ts +++ b/src/scores/pss_4/pss_4.ts @@ -1,6 +1,6 @@ import { PSS4_INPUTS, PSS4_OUTPUTS } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const pss_4: ScoreType = { name: 'Perceived Stress Scale 4 (PSS-4)', @@ -13,7 +13,7 @@ export const pss_4: ScoreType = { const reversedValues = reversedInputs.map(i => MAX_SCORE - i) const allValues = [data.PSS4_Q01, ...reversedValues, data.PSS4_Q04] - const totalScore = _.sum(allValues) + const totalScore = sum(allValues) return { PSS4_SCORE: totalScore, diff --git a/src/scores/sccai/sccai.test.ts b/src/scores/sccai/sccai.test.ts index 4e830f1..1f6af76 100644 --- a/src/scores/sccai/sccai.test.ts +++ b/src/scores/sccai/sccai.test.ts @@ -133,7 +133,7 @@ describe('sccai', function () { }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => sccai_calculation.calculate({ payload: { diff --git a/src/scores/sccai/sccai.ts b/src/scores/sccai/sccai.ts index 8c958b2..9f2033f 100644 --- a/src/scores/sccai/sccai.ts +++ b/src/scores/sccai/sccai.ts @@ -1,6 +1,6 @@ import { SCCAI_INPUTS, SCCAI_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const sccai: ScoreType = { name: 'Simple Clinical Colitis Activity Index (SCCAI)', @@ -8,7 +8,7 @@ export const sccai: ScoreType = { inputSchema: SCCAI_INPUTS, outputSchema: SCCAI_OUTPUT, calculate: ({ data }) => { - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) return { SCCAI: totalScore, diff --git a/src/scores/sf12/sf12.test.ts b/src/scores/sf12/sf12.test.ts index fcd55b2..bf21583 100644 --- a/src/scores/sf12/sf12.test.ts +++ b/src/scores/sf12/sf12.test.ts @@ -95,31 +95,31 @@ describe('sf12', function () { describe('values entered by the user are checked to verify they are inside specified ranges for question 1', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => score.calculate({ payload: { SF12_Q01: "I'm not a number" } }), ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => score.calculate({ payload: { SF12_Q01: -1 } })).toThrow( ZodError, ) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => score.calculate({ payload: { SF12_Q01: 6 } })).toThrow( ZodError, ) }) - it('should throw an InvalidInputsError for question 4', function () { + it('should throw an ZodError for question 4', function () { expect(() => score.calculate({ payload: { SF12_Q04: 3 } })).toThrow( ZodError, ) }) - it('should throw an InvalidInputsError for question 9', function () { + it('should throw an ZodError for question 9', function () { expect(() => score.calculate({ payload: { SF12_Q09: 7 } })).toThrow( ZodError, ) diff --git a/src/scores/sf12/sf12.ts b/src/scores/sf12/sf12.ts index bfa2805..54e908b 100644 --- a/src/scores/sf12/sf12.ts +++ b/src/scores/sf12/sf12.ts @@ -1,7 +1,7 @@ import { areAllValuesDefined } from '../../lib' import { ScoreType } from '../../types' import { SF12_INPUT, SF12_OUTPUT } from './definition' -import _ from 'lodash' +import { round } from 'lodash' export const sf12: ScoreType = { name: '12-Item Short Form Survey (SF12)', @@ -161,8 +161,8 @@ export const sf12: ScoreType = { 60.75781 return { - PHYSICAL_COMPONENT_SCORE: _.round(RAWPCS12, 5), - MENTAL_COMPONENT_SCORE: _.round(RAWMCS12, 5), + PHYSICAL_COMPONENT_SCORE: round(RAWPCS12, 5), + MENTAL_COMPONENT_SCORE: round(RAWMCS12, 5), } }, } diff --git a/src/scores/sst/simple_shoulder_test.test.ts b/src/scores/sst/simple_shoulder_test.test.ts index 774ebaa..e6f9ba5 100644 --- a/src/scores/sst/simple_shoulder_test.test.ts +++ b/src/scores/sst/simple_shoulder_test.test.ts @@ -137,7 +137,7 @@ describe('simple_shoulder_test', function () { }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => sst_calculation.calculate({ payload: { diff --git a/src/scores/sst/simple_shoulder_test.ts b/src/scores/sst/simple_shoulder_test.ts index 43b8200..38a2afa 100644 --- a/src/scores/sst/simple_shoulder_test.ts +++ b/src/scores/sst/simple_shoulder_test.ts @@ -1,6 +1,6 @@ import { SST_INPUTS, SST_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum, round } from 'lodash' export const simple_shoulder_test: ScoreType< typeof SST_INPUTS, @@ -21,12 +21,12 @@ export const simple_shoulder_test: ScoreType< } } - const totalScore = _.sum(Object.values(data)) + const totalScore = sum(Object.values(data)) const percentageScore = (totalScore / totalQuestions) * 100 const ROUND_TO = 2 return { - SST: _.round(percentageScore, ROUND_TO), + SST: round(percentageScore, ROUND_TO), } }, } diff --git a/src/scores/stop_bang/stop_bang.test.ts b/src/scores/stop_bang/stop_bang.test.ts index 41013c2..b8f7dce 100644 --- a/src/scores/stop_bang/stop_bang.test.ts +++ b/src/scores/stop_bang/stop_bang.test.ts @@ -141,7 +141,7 @@ describe('stop_bang', function () { }) describe('when an answer is below 0', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => stop_bang_calculation.calculate({ payload: { @@ -166,7 +166,7 @@ describe('stop_bang', function () { }) }) describe('when an answer is above maximum allowed value', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => stop_bang_calculation.calculate({ payload: { diff --git a/src/scores/stop_bang/stop_bang.ts b/src/scores/stop_bang/stop_bang.ts index bdfb457..adf47b2 100644 --- a/src/scores/stop_bang/stop_bang.ts +++ b/src/scores/stop_bang/stop_bang.ts @@ -4,7 +4,7 @@ import { STOP_BANG_INTERPRETATION_TABLE, } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const stop_bang: ScoreType< typeof STOP_BANG_INPUTS, @@ -39,7 +39,7 @@ export const stop_bang: ScoreType< genderPoint, ] - const totalScore = _.sum(values) + const totalScore = sum(values) return { STOP_BANG: totalScore, diff --git a/src/scores/tampa/tampa.test.ts b/src/scores/tampa/tampa.test.ts index cad5b70..d4038be 100644 --- a/src/scores/tampa/tampa.test.ts +++ b/src/scores/tampa/tampa.test.ts @@ -121,7 +121,7 @@ describe('tampa', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => tampa_calculation.calculate({ payload: { @@ -132,7 +132,7 @@ describe('tampa', function () { }) }) describe('when an answer is not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => tampa_calculation.calculate({ payload: { diff --git a/src/scores/tampa/tampa.ts b/src/scores/tampa/tampa.ts index ade54e9..c60972c 100644 --- a/src/scores/tampa/tampa.ts +++ b/src/scores/tampa/tampa.ts @@ -1,6 +1,6 @@ import { TAMPA_INPUTS, TAMPA_OUTPUT } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum, pick, mapValues, omit } from 'lodash' export const tampa: ScoreType = { name: 'Tampa', @@ -8,13 +8,13 @@ export const tampa: ScoreType = { inputSchema: TAMPA_INPUTS, outputSchema: TAMPA_OUTPUT, calculate: ({ data }) => { - const inverseQuestions = _.pick(data, ['Q04', 'Q08', 'Q12', 'Q16']) - const inverseValues = _.mapValues(inverseQuestions, value => 5 - value) + const inverseQuestions = pick(data, ['Q04', 'Q08', 'Q12', 'Q16']) + const inverseValues = mapValues(inverseQuestions, value => 5 - value) - const nonInverseValues = _.omit(data, Object.keys(inverseQuestions)) + const nonInverseValues = omit(data, Object.keys(inverseQuestions)) const combinedValues = { ...inverseValues, ...nonInverseValues } - const totalScore = _.sum(Object.values(combinedValues)) + const totalScore = sum(Object.values(combinedValues)) const hasMovementFear = totalScore >= 37 const interpretation = hasMovementFear diff --git a/src/scores/yp_core/yp_core.test.ts b/src/scores/yp_core/yp_core.test.ts index 513bd1d..92e90db 100644 --- a/src/scores/yp_core/yp_core.test.ts +++ b/src/scores/yp_core/yp_core.test.ts @@ -61,7 +61,7 @@ describe('yp_core', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => yp_core_calculation.calculate({ payload: { diff --git a/src/scores/yp_core/yp_core.ts b/src/scores/yp_core/yp_core.ts index 1bc926c..6f8d389 100644 --- a/src/scores/yp_core/yp_core.ts +++ b/src/scores/yp_core/yp_core.ts @@ -4,7 +4,7 @@ import { YP_CORE_OUTPUT, } from './definition' import { ScoreType } from '../../types' -import _ from 'lodash' +import { sum } from 'lodash' export const yp_core: ScoreType = { @@ -18,7 +18,7 @@ export const yp_core: ScoreType = if (validInputs.length === 0) return { YP_CORE_TOTAL_SCORE: null, YP_CORE_INTERPRETATION: null } - const totalScore = (_.sum(validInputs) / validInputs.length) * 10 + const totalScore = (sum(validInputs) / validInputs.length) * 10 return { YP_CORE_TOTAL_SCORE: totalScore, diff --git a/todo/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.test.ts b/todo/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.test.ts deleted file mode 100644 index f803f97..0000000 --- a/todo/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.test.ts +++ /dev/null @@ -1,121 +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__/CHA2DS2_VASc_Score_test_responses' -import { CHA2DS2_VASc_Score } from './CHA2DS2_VASc_Score' -import { CHA2DS2_VASC_SCORE_INPUTS } from './definition' - -const BEST_SCORE = 0 -const WORST_SCORE = 9 - -const calculation = execute_test_calculation(CHA2DS2_VASc_Score) - -describe('CHA2DS2_VASc_Score', function () { - it('CHA2DS2_VASc_Score calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('CHA2DS2_VASc_Score') - }) - - describe('basic assumptions', function () { - const outcome = calculation(best_response) - - it('should return 1 calculation result', function () { - expect(outcome).toHaveLength(1) - }) - - it('should have the expected calculation result ids', function () { - const EXPECTED_CALCULATION_ID = ['CHA2DS2_VASC_SCORE'] - - 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 = [ - '1_AGE', - '2_SEX', - '3_CHF_HISTORY', - '4_HYPERTENSION_HISTORY', - '5_STROKE_TIA_THROMBOEMBOLISM_HISTORY', - '6_VASCULAR_DISEASE_HISTORY', - '7_DIABETES_HISTORY', - ] - - const configured_input_ids = get_input_ids_from_calculation_blueprint( - CHA2DS2_VASC_SCORE_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(() => - calculation({ - '7_DIABETES_HISTORY': 3, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with an empty response', function () { - const outcome = calculation({}) - - it('should return undefined result and a missing status for the "Patient interview" score', function () { - const score = view_result('CHA2DS2_VASC_SCORE')(outcome) - const status = view_status('CHA2DS2_VASC_SCORE')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with the best response', function () { - const outcome = calculation(best_response) - - it('should return the best score', function () { - const score = view_result('CHA2DS2_VASC_SCORE')(outcome) - - expect(score).toEqual(BEST_SCORE) - }) - }) - describe('when called with the worst response', function () { - const outcome = calculation(worst_response) - - it('should return the worst "Patient interview" score', function () { - const score = view_result('CHA2DS2_VASC_SCORE')(outcome) - - expect(score).toEqual(WORST_SCORE) - }) - }) - - describe('when called with a random response', function () { - const outcome = calculation(random_response) - - it('should return the expected score', function () { - const score = view_result('CHA2DS2_VASC_SCORE')(outcome) - const EXPECTED_SCORE = 6 - - expect(score).toEqual(EXPECTED_SCORE) - }) - }) - }) -}) diff --git a/todo/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.ts b/todo/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.ts deleted file mode 100644 index 3a33bf0..0000000 --- a/todo/CHA2DS2_VASc_Score/CHA2DS2_VASc_Score.ts +++ /dev/null @@ -1,55 +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 { - CHA2DS2_VASC_SCORE_INPUTS, - CHA2DS2_VASC_SCORE_OUTPUT, -} from './definition' - -const calculate_points = ( - 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 === 0) - return [ - { - id: 'CHA2DS2_VASC_SCORE', - score: MISSING_MESSAGE, - }, - ] - - return [ - { - id: 'CHA2DS2_VASC_SCORE', - score: R.sum(valid_inputs), - }, - ] -} - -export const specific_steps_cha2ds2_vasc_score_calc = [ - calculate_points, - add_raw_values_to_inputs(CHA2DS2_VASC_SCORE_INPUTS), -] - -export const CHA2DS2_VASc_Score: CalculationType = create_calculation({ - calculation_name: 'CHA₂DS₂-VASc Score for Atrial Fibrillation Stroke Risk', - readme_location: __dirname, - calculation_steps: specific_steps_cha2ds2_vasc_score_calc, - calculation_definition: { - input_definition: CHA2DS2_VASC_SCORE_INPUTS, - output_definition: CHA2DS2_VASC_SCORE_OUTPUT, - }, -}) diff --git a/todo/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_output.ts b/todo/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_output.ts deleted file mode 100644 index 4339802..0000000 --- a/todo/CHA2DS2_VASc_Score/definition/CHA2DS2_VASc_Score_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const CHA2DS2_VASC_SCORE_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'CHA2DS2_VASC_SCORE', - label: { en: 'CHA₂DS₂-VASc Score' }, - type: 'number', - }, -] diff --git a/todo/IBD_control/IBD_control.test.ts b/todo/IBD_control/IBD_control.test.ts deleted file mode 100644 index 4706d47..0000000 --- a/todo/IBD_control/IBD_control.test.ts +++ /dev/null @@ -1,180 +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 { CALCULATIONS } from '../calculation_library' -import { get_input_ids_from_calculation_blueprint } from '../shared_functions' -import { - max_response, - median_response, - min_response, - random_response, -} from './__testdata__/IBD_control_responses' -import { IBD_CONTROL_INPUTS } from './definition/ibd_control_inputs' -import { IBD_control } from './IBD_control' - -const IBD_CONTROL_8_MIN_SCORE = 0 -const IBD_CONTROL_8_MEDIAN_SCORE = 8 -const IBD_CONTROL_8_MAX_SCORE = 16 - -const IBD_CONTROL_VAS_MIN_SCORE = 0 -const IBD_CONTROL_VAS_MEDIAN_SCORE = 50 -const IBD_CONTROL_VAS_MAX_SCORE = 100 - -const ibd_control_calculation = execute_test_calculation(IBD_control) - -describe('IBD_control', function () { - it('IBD_control calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('IBD_control') - }) - - describe('the score includes the correct input fields', function () { - it('should use the correct input fields', function () { - const EXPECTED_CALCULATION_INPUT_IDS = [ - 'ibd_control_1a', - 'ibd_control_1b', - 'ibd_control_3a', - 'ibd_control_3b', - 'ibd_control_3c', - 'ibd_control_3d', - 'ibd_control_3e', - 'ibd_control_3f', - 'ibd_control_5', - ] - - const configured_calculation_input_ids = - get_input_ids_from_calculation_blueprint(IBD_CONTROL_INPUTS) - - expect(configured_calculation_input_ids).to.have.members( - EXPECTED_CALCULATION_INPUT_IDS, - ) - }) - }) - - describe('each calculated score includes the correct output result and correct score title', function () { - const outcome = ibd_control_calculation(min_response) - - it('should return 2 scores', function () { - expect(outcome).toHaveLength(2) - }) - - it('should have the correct calculation ids', function () { - const EXPECTED_CALCULATION_IDS = ['IBD_CONTROL_8', 'IBD_CONTROL_VAS'] - - const extracted_calculation_ids_from_outcome = - get_result_ids_from_calculation_output(outcome) - - expect(EXPECTED_CALCULATION_IDS).toEqual( - extracted_calculation_ids_from_outcome, - ) - }) - }) - - describe('each calculated score includes the correct formula and outputs the correct result', function () { - describe('when a minimum response is passed', function () { - const outcome = ibd_control_calculation(min_response) - - it('should return the minimum score for IBD-Control-8', function () { - const IBD_CONTROL_8_SCORE = view_result('IBD_CONTROL_8')(outcome) - expect(IBD_CONTROL_8_SCORE).toEqual(IBD_CONTROL_8_MIN_SCORE) - }) - - it('should return the minimum score for IBD-Control-VAS', function () { - const IBD_CONTROL_VAS_SCORE = view_result('IBD_CONTROL_VAS')(outcome) - expect(IBD_CONTROL_VAS_SCORE).toEqual(IBD_CONTROL_VAS_MIN_SCORE) - }) - }) - - describe('when a median response is passed', function () { - const outcome = ibd_control_calculation(median_response) - - it('should return the median score for IBD-Control-8', function () { - const IBD_CONTROL_8_SCORE = view_result('IBD_CONTROL_8')(outcome) - expect(IBD_CONTROL_8_SCORE).toEqual(IBD_CONTROL_8_MEDIAN_SCORE) - }) - - it('should return the median score for IBD-Control-VAS', function () { - const IBD_CONTROL_VAS_SCORE = view_result('IBD_CONTROL_VAS')(outcome) - expect(IBD_CONTROL_VAS_SCORE).toEqual(IBD_CONTROL_VAS_MEDIAN_SCORE) - }) - }) - - describe('when a maximum response is passed', function () { - const outcome = ibd_control_calculation(max_response) - - it('should return the maximum score for IBD-Control-8', function () { - const IBD_CONTROL_8_SCORE = view_result('IBD_CONTROL_8')(outcome) - expect(IBD_CONTROL_8_SCORE).toEqual(IBD_CONTROL_8_MAX_SCORE) - }) - - it('should return the maximum score for IBD-Control-VAS', function () { - const IBD_CONTROL_VAS_SCORE = view_result('IBD_CONTROL_VAS')(outcome) - expect(IBD_CONTROL_VAS_SCORE).toEqual(IBD_CONTROL_VAS_MAX_SCORE) - }) - }) - - describe('when a random response is passed', function () { - const outcome = ibd_control_calculation(random_response) - - it('should return the expected score for IBD-Control-8', function () { - const IBD_CONTROL_8_SCORE = view_result('IBD_CONTROL_8')(outcome) - const EXPECTED_CONTROL_8_SCORE = 7 - expect(IBD_CONTROL_8_SCORE).toEqual(EXPECTED_CONTROL_8_SCORE) - }) - - it('should return the expected score for IBD-Control-VAS', function () { - const IBD_CONTROL_VAS_SCORE = view_result('IBD_CONTROL_VAS')(outcome) - const EXPECTED_CONTROL_VAS_SCORE = 54 - expect(IBD_CONTROL_VAS_SCORE).toEqual(EXPECTED_CONTROL_VAS_SCORE) - }) - }) - }) - - describe('a score is only calculated when all mandatory fields are entered', function () { - describe('when an empty response is passed', function () { - const outcome = ibd_control_calculation({}) - - it('should return MISSING_MESSAGE for the IBD-Control-8', function () { - const IBD_CONTROL_8_SCORE = view_result('IBD_CONTROL_8')(outcome) - expect(IBD_CONTROL_8_SCORE).toEqual(undefined) - }) - - it('should return MISSING_MESSAGE for the IBD-Control-VAS', function () { - const IBD_CONTROL_VAS_SCORE = view_result('IBD_CONTROL_VAS')(outcome) - expect(IBD_CONTROL_VAS_SCORE).toEqual(undefined) - }) - }) - }) - - describe('values entered by the user are checked to verify they are inside specified ranges', function () { - describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ibd_control_calculation({ - ibd_control_1a: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when an answer is below the allowed answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ibd_control_calculation({ - ibd_control_1a: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when an answer is above the allowed answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ibd_control_calculation({ - ibd_control_5: 101, // VAS - }), - ).toThrow(InvalidInputsError) - }) - }) - }) -}) diff --git a/todo/IBD_control/IBD_control.ts b/todo/IBD_control/IBD_control.ts deleted file mode 100644 index 39d938f..0000000 --- a/todo/IBD_control/IBD_control.ts +++ /dev/null @@ -1,126 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { - inputIdLens, - rawInputValueLens, -} from '../../lib/calculation_variants/api/input/lenses' -import { - add_raw_values_to_inputs, - do_all_required_inputs_have_a_valid_value, - get_valid_values, -} from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../PARAMETERS' -import { - IBD_CONTROL_INPUTS, - IBD_CONTROL_OUTPUT, - NO_TREATMENT, -} from './definition' - -const IBD_CONTROL_8_CALCULATION_NAME = 'IBD_CONTROL_8' -const IBD_CONTROL_VAS_CALCULATION_NAME = 'IBD_CONTROL_VAS' - -/** - * Input ibd_control_1b: no treatment (999) must be replaced with value 1. - * This can't be done in form itself since there's already an answer with that value. - */ -const recode_input_ibd_control_1b = ( - calculation_input: Array, -): Array => - R.map(input => { - const input_id = R.view(inputIdLens, input) - const answer = R.view(rawInputValueLens, input) - - if (input_id === 'ibd_control_1b') { - if (Number(answer) === NO_TREATMENT) { - return R.set(rawInputValueLens, 1, input) - } - - return input - } - - return input - }, calculation_input) - -const calculate_ibd_control_8_and_vas_score = ( - calculation_input: Array, -): WIPCalculationResultType => { - const IBD_CONTROL_8_QUESTIONS = [ - 'ibd_control_1a', - 'ibd_control_1b', - 'ibd_control_3a', - 'ibd_control_3b', - 'ibd_control_3c', - 'ibd_control_3d', - 'ibd_control_3e', - 'ibd_control_3f', - ] - - const calclation_input_ibd_control_8_score = R.filter( - input => IBD_CONTROL_8_QUESTIONS.includes(R.view(inputIdLens, input)), - calculation_input, - ) - - // We only need "ibd_control_5" (VAS) - const calclation_input_ibd_control_vas_score = R.filter( - input => R.view(inputIdLens, input) === 'ibd_control_5', - calculation_input, - ) - - let IBD_CONTROL_8_SCORE = MISSING_MESSAGE - let IBD_CONTROL_VAS = MISSING_MESSAGE - - if ( - do_all_required_inputs_have_a_valid_value( - calclation_input_ibd_control_8_score, - ) - ) { - //@ts-expect-error to do - IBD_CONTROL_8_SCORE = R.sum( - get_valid_values(calclation_input_ibd_control_8_score), - ) - } - - if ( - do_all_required_inputs_have_a_valid_value( - calclation_input_ibd_control_vas_score, - ) - ) { - //@ts-expect-error to do - IBD_CONTROL_VAS = R.head( - get_valid_values(calclation_input_ibd_control_vas_score), - ) - } - - return [ - { - id: IBD_CONTROL_VAS_CALCULATION_NAME, - score: IBD_CONTROL_VAS, - }, - { - id: IBD_CONTROL_8_CALCULATION_NAME, - score: IBD_CONTROL_8_SCORE, - }, - ] -} - -export const specific_steps_ibd_control_calc = [ - calculate_ibd_control_8_and_vas_score, - recode_input_ibd_control_1b, - add_raw_values_to_inputs(IBD_CONTROL_INPUTS), -] - -export const IBD_control: CalculationType = create_calculation({ - calculation_name: 'IBD-Control', - readme_location: __dirname, - calculation_steps: specific_steps_ibd_control_calc, - calculation_definition: { - input_definition: IBD_CONTROL_INPUTS, - output_definition: IBD_CONTROL_OUTPUT, - }, -}) diff --git a/todo/IBD_control/definition/ibd_control_output.ts b/todo/IBD_control/definition/ibd_control_output.ts deleted file mode 100644 index e91909c..0000000 --- a/todo/IBD_control/definition/ibd_control_output.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const IBD_CONTROL_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'IBD_CONTROL_8', - label: { en: 'IBD-Control-8 Score' }, - type: 'number', - }, - { - subresult_id: 'IBD_CONTROL_VAS', - label: { en: 'IBD-Control-VAS Score' }, - type: 'number', - }, -] diff --git a/todo/KCCQ_12/KCCQ_12.test.ts b/todo/KCCQ_12/KCCQ_12.test.ts index e2bf182..f1f237a 100644 --- a/todo/KCCQ_12/KCCQ_12.test.ts +++ b/todo/KCCQ_12/KCCQ_12.test.ts @@ -384,30 +384,30 @@ describe('KCCQ_12', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => kccq12_calculation({ KCCQ12_Q1_A: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [1,6] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => kccq12_calculation({ KCCQ12_Q1_A: 0, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [1,6] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => kccq12_calculation({ KCCQ12_Q1_A: 7, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/audit/audit.test.ts b/todo/audit/audit.test.ts index 5e123fb..c4a6708 100644 --- a/todo/audit/audit.test.ts +++ b/todo/audit/audit.test.ts @@ -59,28 +59,26 @@ describe('audit', function () { describe('validation', function () { describe('when called with a response where there are answers out of the expected [0-4] range', function () { describe('when an answer is above the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => audit_calculation({ AUDIT_Q01: 10 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => audit_calculation({ AUDIT_Q01: 10 })).toThrow(ZodError) }) }) describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => audit_calculation({ AUDIT_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => audit_calculation({ AUDIT_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/breast_q/breast_conserving/breast_q.test.ts b/todo/breast_q/breast_conserving/breast_q.test.ts index a240854..234eddf 100644 --- a/todo/breast_q/breast_conserving/breast_q.test.ts +++ b/todo/breast_q/breast_conserving/breast_q.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -625,30 +625,30 @@ describe('breast_q_conserving_therapy_pre_and_postoperative', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => breast_q_calculation({ PSYCHOSOCIAL_WELLBEING_PREOP_POSTOP_A: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => breast_q_calculation({ PSYCHOSOCIAL_WELLBEING_PREOP_POSTOP_A: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => breast_q_calculation({ PSYCHOSOCIAL_WELLBEING_PREOP_POSTOP_A: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/cade_q/short_version/cade_q_sv.test.ts b/todo/cade_q/short_version/cade_q_sv.test.ts index 4b49315..05b9a1f 100644 --- a/todo/cade_q/short_version/cade_q_sv.test.ts +++ b/todo/cade_q/short_version/cade_q_sv.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -79,32 +79,32 @@ describe('cade_q_sv', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cade_q_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when called with a response where there are above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cade_q_calculation({ Q01: 3, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when called with a response where there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cade_q_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/caregiver_strain_index/caregiver_strain_index.test.ts b/todo/caregiver_strain_index/caregiver_strain_index.test.ts deleted file mode 100644 index 94fc6af..0000000 --- a/todo/caregiver_strain_index/caregiver_strain_index.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { expect } from 'chai' -import { compose } from 'ramda' - -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 { MISSING_STATUS } from '../../PARAMETERS' -import { CALCULATIONS } from '../calculation_library' -import { - get_input_ids_from_calculation_blueprint, - view_status, -} from '../shared_functions' -import { - max_response, - median_response, - min_response, - random_response, -} from './__testdata__/caregiver_strain_index_test_responses' -import { - caregiver_strain_index, - // eslint-disable-next-line sort-imports - CAREGIVER_STRAIN_INDEX_ID, -} from './caregiver_strain_index' -import { CAREGIVER_STRAIN_INDEX_INPUTS } from './definition/caregiver_strain_index_inputs' - -const CSI_MIN_SCORE = 0 -const CSI_MEDIAN_SCORE = 6 // or 7 but test is written for 6 -const CSI_MAX_SCORE = 13 - -const caregiver_strain_index_calculation = execute_test_calculation( - caregiver_strain_index, -) - -describe('caregiver_strain_index', function () { - it('caregiver_strain_index calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('caregiver_strain_index') - }) - - describe('basic assumption', function () { - describe('the score includes the correct input fields', function () { - it('should use the correct input fields', function () { - const EXPECTED_CALCULATION_INPUT_IDS = [ - 'CSI_Q01', - 'CSI_Q02', - 'CSI_Q03', - 'CSI_Q04', - 'CSI_Q05', - 'CSI_Q06', - 'CSI_Q07', - 'CSI_Q08', - 'CSI_Q09', - 'CSI_Q10', - 'CSI_Q11', - 'CSI_Q12', - 'CSI_Q13', - ] - - const CONFIGURED_CALCULATION_INPUT_IDS = - get_input_ids_from_calculation_blueprint( - CAREGIVER_STRAIN_INDEX_INPUTS, - ) - - expect(EXPECTED_CALCULATION_INPUT_IDS).to.have.members( - CONFIGURED_CALCULATION_INPUT_IDS, - ) - }) - }) - - describe('each calculated score includes the correct output result and correct score title', function () { - const outcome = caregiver_strain_index_calculation(min_response) - - it('should calculate a single score', function () { - expect(outcome).toHaveLength(1) - }) - - it('should have the correct calculation id', function () { - const EXPECTED_CALCULATION_ID = ['CAREGIVER_STRAIN_INDEX'] - const configured_calculation_id = - get_result_ids_from_calculation_output(outcome) - - expect(configured_calculation_id).toEqual(EXPECTED_CALCULATION_ID) - }) - }) - }) - - describe('score calculations', function () { - describe('each calculated score includes the correct formula and outputs the correct result', function () { - describe('when a minimum response is passed', function () { - it('should return the minimum score', function () { - const score = compose( - view_result(CAREGIVER_STRAIN_INDEX_ID), - caregiver_strain_index_calculation, - )(min_response) - - expect(score).toEqual(CSI_MIN_SCORE) - }) - }) - - describe('when a median response is passed', function () { - it('should return the median score', function () { - const score = compose( - view_result(CAREGIVER_STRAIN_INDEX_ID), - caregiver_strain_index_calculation, - )(median_response) - - expect(score).toEqual(CSI_MEDIAN_SCORE) - }) - }) - - describe('when a maximum response is passed', function () { - it('should return the maximum score', function () { - const score = compose( - view_result(CAREGIVER_STRAIN_INDEX_ID), - caregiver_strain_index_calculation, - )(max_response) - - expect(score).toEqual(CSI_MAX_SCORE) - }) - }) - - describe('when a random response is passed', function () { - it('should return the expected score', function () { - const score = compose( - view_result(CAREGIVER_STRAIN_INDEX_ID), - caregiver_strain_index_calculation, - )(random_response) - - const EXPECTED_SCORE = 7 - expect(score).toEqual(EXPECTED_SCORE) - }) - }) - }) - }) - - describe('validations', function () { - describe('a score is only calculated when all mandatory fields are entered', function () { - describe('when an empty response is passed', function () { - it('should return undefined result & missing status', function () { - const outcome = caregiver_strain_index_calculation({}) - const result = view_result(CAREGIVER_STRAIN_INDEX_ID)(outcome) - const status = view_status(CAREGIVER_STRAIN_INDEX_ID)(outcome) - - expect(result).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('values entered by the user are checked to verify they are inside specified ranges', function () { - describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - caregiver_strain_index_calculation({ - CSI_Q01: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when an answer is below 0 (i.e. not 0 = no or 1 = yes)', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - caregiver_strain_index_calculation({ - CSI_Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when an answer is above 1 (i.e. not 0 = no or 1 = yes)', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - caregiver_strain_index_calculation({ - CSI_Q01: 2, - }), - ).toThrow(InvalidInputsError) - }) - }) - }) - }) -}) diff --git a/todo/caregiver_strain_index/caregiver_strain_index.ts b/todo/caregiver_strain_index/caregiver_strain_index.ts deleted file mode 100644 index cc8f22f..0000000 --- a/todo/caregiver_strain_index/caregiver_strain_index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { - add_raw_values_to_inputs, - do_all_required_inputs_have_a_valid_value, - get_valid_values, -} from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../PARAMETERS' -import { - CAREGIVER_STRAIN_INDEX_INPUTS, - CAREGIVER_STRAIN_INDEX_OUTPUT, -} from './definition' - -export const CAREGIVER_STRAIN_INDEX_ID = 'CAREGIVER_STRAIN_INDEX' - -const calculate_score = ( - csi_inputs_with_answers: Array, -): WIPCalculationResultType => { - if (do_all_required_inputs_have_a_valid_value(csi_inputs_with_answers)) { - const total_score = R.sum(get_valid_values(csi_inputs_with_answers)) - - return [ - { - id: CAREGIVER_STRAIN_INDEX_ID, - score: total_score, - }, - ] - } - - return [ - { - id: CAREGIVER_STRAIN_INDEX_ID, - score: MISSING_MESSAGE, - }, - ] -} - -export const specific_steps_caregiver_strain_index_calc = [ - calculate_score, - add_raw_values_to_inputs(CAREGIVER_STRAIN_INDEX_INPUTS), -] - -export const caregiver_strain_index: CalculationType = create_calculation({ - calculation_name: 'Caregiver Strain Index (CSI)', - readme_location: __dirname, - calculation_steps: specific_steps_caregiver_strain_index_calc, - calculation_definition: { - input_definition: CAREGIVER_STRAIN_INDEX_INPUTS, - output_definition: CAREGIVER_STRAIN_INDEX_OUTPUT, - }, -}) diff --git a/todo/caregiver_strain_index/definition/caregiver_strain_index_output.ts b/todo/caregiver_strain_index/definition/caregiver_strain_index_output.ts deleted file mode 100644 index 670a6c2..0000000 --- a/todo/caregiver_strain_index/definition/caregiver_strain_index_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const CAREGIVER_STRAIN_INDEX_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'CAREGIVER_STRAIN_INDEX', - label: { en: 'CSI score' }, - type: 'number', - }, -] diff --git a/todo/cat/cat.test.ts b/todo/cat/cat.test.ts index 5294970..cae937a 100644 --- a/todo/cat/cat.test.ts +++ b/todo/cat/cat.test.ts @@ -67,12 +67,12 @@ describe('cat', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cat_calculation({ '1_COUGH': -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/ccq/ccq.test.ts b/todo/ccq/ccq.test.ts index 6a3051b..5de068f 100644 --- a/todo/ccq/ccq.test.ts +++ b/todo/ccq/ccq.test.ts @@ -238,30 +238,30 @@ describe('ccq', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ccq_calclation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ccq_calclation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ccq_calclation({ Q01: 7, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/cdlqi/cdlqi.test.ts b/todo/cdlqi/cdlqi.test.ts index 7d835b4..311a550 100644 --- a/todo/cdlqi/cdlqi.test.ts +++ b/todo/cdlqi/cdlqi.test.ts @@ -180,31 +180,31 @@ describe('cdlqi', function () { describe('when called with a response with answers out of the expected [0,3] range', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cdlqi_calculation({ CDLQI_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0,3] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cdlqi_calculation({ CDLQI_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0,3] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => cdlqi_calculation({ CDLQI_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/comi/back/comi_back.test.ts b/todo/comi/back/comi_back.test.ts index aabcd3e..9c1e915 100644 --- a/todo/comi/back/comi_back.test.ts +++ b/todo/comi/back/comi_back.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -79,27 +79,21 @@ describe('comi_back', function () { describe('when answer on item 1a is out of the expected range', function () { describe('when answer < 0', function () { - it('should throw an InvalidInputsError', function () { - expect(() => comi_back_calculation({ item_1a: -1 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => comi_back_calculation({ item_1a: -1 })).toThrow(ZodError) }) }) describe('when answer > 10', function () { - it('should throw an InvalidInputsError', function () { - expect(() => comi_back_calculation({ item_1a: 11 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => comi_back_calculation({ item_1a: 11 })).toThrow(ZodError) }) }) }) describe('when answer on item 3 is not expected', function () { - it('should throw an InvalidInputsError', function () { - expect(() => comi_back_calculation({ item_3: 4 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => comi_back_calculation({ item_3: 4 })).toThrow(ZodError) }) }) diff --git a/todo/comi/neck/comi_neck.test.ts b/todo/comi/neck/comi_neck.test.ts index f4e8820..bb38e4d 100644 --- a/todo/comi/neck/comi_neck.test.ts +++ b/todo/comi/neck/comi_neck.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -79,27 +79,21 @@ describe('comi_neck', function () { describe('when answer on item 1a is out of the expected range', function () { describe('when answer < 0', function () { - it('should throw an InvalidInputsError', function () { - expect(() => comi_neck_calculation({ item_1a: -1 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => comi_neck_calculation({ item_1a: -1 })).toThrow(ZodError) }) }) describe('when answer > 10', function () { - it('should throw an InvalidInputsError', function () { - expect(() => comi_neck_calculation({ item_1a: 11 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => comi_neck_calculation({ item_1a: 11 })).toThrow(ZodError) }) }) }) describe('when answer on item 3 is not expected', function () { - it('should throw an InvalidInputsError', function () { - expect(() => comi_neck_calculation({ item_3: 4 })).toThrow( - InvalidInputsError, - ) + it('should throw an ZodError', function () { + expect(() => comi_neck_calculation({ item_3: 4 })).toThrow(ZodError) }) }) diff --git a/todo/compass_31/compass_31.test.ts b/todo/compass_31/compass_31.test.ts index ee68de1..5ac6655 100644 --- a/todo/compass_31/compass_31.test.ts +++ b/todo/compass_31/compass_31.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -157,32 +157,32 @@ describe('compass_31', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => compass_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => compass_calculation({ Q01: 8, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => compass_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/constant_murley_score/orthotoolkit_version/constant_murley_score.test.ts b/todo/constant_murley_score/orthotoolkit_version/constant_murley_score.test.ts index 3eb759a..77f91f6 100644 --- a/todo/constant_murley_score/orthotoolkit_version/constant_murley_score.test.ts +++ b/todo/constant_murley_score/orthotoolkit_version/constant_murley_score.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -332,7 +332,7 @@ describe('constant_murley_score_orthotoolkit', function () { cms_calculation({ Q01_PAIN_SCORE: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -341,7 +341,7 @@ describe('constant_murley_score_orthotoolkit', function () { cms_calculation({ Q01_PAIN_SCORE: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -350,7 +350,7 @@ describe('constant_murley_score_orthotoolkit', function () { cms_calculation({ Q01_PAIN_SCORE: 16, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/core_om/core_om.test.ts b/todo/core_om/core_om.test.ts deleted file mode 100644 index 70a35ac..0000000 --- a/todo/core_om/core_om.test.ts +++ /dev/null @@ -1,560 +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, - median_response, - random_response, - worst_response, -} from './__testdata__/core_om_responses' -import { core_om } from './core_om' -import { CORE_OM_INPUTS } from './definition' - -const core_om_calculation = execute_test_calculation(core_om) - -describe('core_om', function () { - it('core_om calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('core_om') - }) - - describe('the score includes the correct input fields', function () { - it('should use the correct input fields', function () { - const EXPECTED_CALCULATION_INPUT_IDS = [ - 'CORE_OM_Q01', - 'CORE_OM_Q02', - 'CORE_OM_Q03', - 'CORE_OM_Q04', - 'CORE_OM_Q05', - 'CORE_OM_Q06', - 'CORE_OM_Q07', - 'CORE_OM_Q08', - 'CORE_OM_Q09', - 'CORE_OM_Q10', - 'CORE_OM_Q11', - 'CORE_OM_Q12', - 'CORE_OM_Q13', - 'CORE_OM_Q14', - 'CORE_OM_Q15', - 'CORE_OM_Q16', - 'CORE_OM_Q17', - 'CORE_OM_Q18', - 'CORE_OM_Q19', - 'CORE_OM_Q20', - 'CORE_OM_Q21', - 'CORE_OM_Q22', - 'CORE_OM_Q23', - 'CORE_OM_Q24', - 'CORE_OM_Q25', - 'CORE_OM_Q26', - 'CORE_OM_Q27', - 'CORE_OM_Q28', - 'CORE_OM_Q29', - 'CORE_OM_Q30', - 'CORE_OM_Q31', - 'CORE_OM_Q32', - 'CORE_OM_Q33', - 'CORE_OM_Q34', - ] - - const configured_calculation_input_ids = - get_input_ids_from_calculation_blueprint(CORE_OM_INPUTS) - - expect(configured_calculation_input_ids).to.have.members( - EXPECTED_CALCULATION_INPUT_IDS, - ) - }) - }) - - describe('each calculated score includes the correct output result and correct score title', function () { - const outcome = core_om_calculation(best_response) - - it('should calculate 4 scoreS', function () { - expect(outcome).toHaveLength(10) - }) - - it('should have the correct calculation ids', function () { - const configured_calculation_id = - get_result_ids_from_calculation_output(outcome) - - expect(configured_calculation_id).toEqual([ - 'SUBJECTIVE_WELL_BEING_DEFICITS_RAW', - 'SUBJECTIVE_WELL_BEING_DEFICITS_MEAN', - 'PROBLEMS_SYMPTOMS_RAW', - 'PROBLEMS_SYMPTOMS_MEAN', - 'LIFE_FUNCTIONING_DIFFICULTIES_RAW', - 'LIFE_FUNCTIONING_DIFFICULTIES_MEAN', - 'RISK_HARM_RAW', - 'RISK_HARM_MEAN', - 'TOTAL_RAW', - 'TOTAL_MEAN', - ]) - }) - }) - - describe('each calculated score includes the correct formula and outputs the correct result', function () { - describe('when the best response is passed', function () { - const outcome = core_om_calculation(best_response) - const BEST_SCORE = 0 - - it('should return the best raw score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_RAW')( - outcome, - ) - - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best mean score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_MEAN')( - outcome, - ) - - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best raw for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_RAW')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best mean score for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_MEAN')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best raw score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_RAW')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best mean score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_MEAN')( - outcome, - ) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best raw score for Risk/harm', function () { - const result = view_result('RISK_HARM_RAW')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best mean score for Risk/harm', function () { - const result = view_result('RISK_HARM_MEAN')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best raw score for Total', function () { - const result = view_result('TOTAL_RAW')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - - it('should return the best mean score for Total', function () { - const result = view_result('TOTAL_MEAN')(outcome) - expect(result).toEqual(BEST_SCORE) - }) - }) - - describe('when a median response is passed', function () { - const outcome = core_om_calculation(median_response) - const MEDIAN_MEAN_SCORE = 2 - - it('should return the median raw score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_RAW')( - outcome, - ) - const MEDIAN_RAW_SCORE = 8 - - expect(result).toEqual(MEDIAN_RAW_SCORE) - }) - - it('should return the median mean score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_MEAN')( - outcome, - ) - - expect(result).toEqual(MEDIAN_MEAN_SCORE) - }) - - it('should return the median raw for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_RAW')(outcome) - const MEDIAN_RAW_SCORE = 24 - - expect(result).toEqual(MEDIAN_RAW_SCORE) - }) - - it('should return the median mean score for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_MEAN')(outcome) - expect(result).toEqual(MEDIAN_MEAN_SCORE) - }) - - it('should return the median raw score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_RAW')(outcome) - const MEDIAN_RAW_SCORE = 24 - - expect(result).toEqual(MEDIAN_RAW_SCORE) - }) - - it('should return the median mean score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_MEAN')( - outcome, - ) - expect(result).toEqual(MEDIAN_MEAN_SCORE) - }) - - it('should return the median raw score for Risk/harm', function () { - const result = view_result('RISK_HARM_RAW')(outcome) - const MEDIAN_RAW_SCORE = 12 - - expect(result).toEqual(MEDIAN_RAW_SCORE) - }) - - it('should return the median mean score for Risk/harm', function () { - const result = view_result('RISK_HARM_MEAN')(outcome) - expect(result).toEqual(MEDIAN_MEAN_SCORE) - }) - - it('should return the median raw score for Total', function () { - const result = view_result('TOTAL_RAW')(outcome) - const MEDIAN_RAW_SCORE = 68 - - expect(result).toEqual(MEDIAN_RAW_SCORE) - }) - - it('should return the median mean score for Total', function () { - const result = view_result('TOTAL_MEAN')(outcome) - expect(result).toEqual(MEDIAN_MEAN_SCORE) - }) - }) - - describe('when the worst response is passed', function () { - const outcome = core_om_calculation(worst_response) - const WORST_MEAN_SCORE = 4 - - it('should return the worst raw score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_RAW')( - outcome, - ) - const WORST_RAW_SCORE = 16 - - expect(result).toEqual(WORST_RAW_SCORE) - }) - - it('should return the worst mean score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_MEAN')( - outcome, - ) - - expect(result).toEqual(WORST_MEAN_SCORE) - }) - - it('should return the worst raw score for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_RAW')(outcome) - const WORST_RAW_SCORE = 48 - - expect(result).toEqual(WORST_RAW_SCORE) - }) - - it('should return the worst mean score for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_MEAN')(outcome) - expect(result).toEqual(WORST_MEAN_SCORE) - }) - - it('should return the worst raw score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_RAW')(outcome) - const WORST_RAW_SCORE = 48 - - expect(result).toEqual(WORST_RAW_SCORE) - }) - - it('should return the worst mean score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_MEAN')( - outcome, - ) - expect(result).toEqual(WORST_MEAN_SCORE) - }) - - it('should return the worst raw score for Risk/harm', function () { - const result = view_result('RISK_HARM_RAW')(outcome) - const WORST_RAW_SCORE = 24 - - expect(result).toEqual(WORST_RAW_SCORE) - }) - - it('should return the worst mean score for Risk/harm', function () { - const result = view_result('RISK_HARM_MEAN')(outcome) - expect(result).toEqual(WORST_MEAN_SCORE) - }) - - it('should return the worst raw score for Total', function () { - const result = view_result('TOTAL_RAW')(outcome) - const WORST_RAW_SCORE = 136 - - expect(result).toEqual(WORST_RAW_SCORE) - }) - - it('should return the worst mean score for Total', function () { - const result = view_result('TOTAL_MEAN')(outcome) - expect(result).toEqual(WORST_MEAN_SCORE) - }) - }) - - describe('when a random response is passed', function () { - const outcome = core_om_calculation(random_response) - - it('should return the expected raw score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_RAW')( - outcome, - ) - const EXPECTED_RAW_SCORE = 2 - - expect(result).toEqual(EXPECTED_RAW_SCORE) - }) - - it('should return the expected mean score for Subjective well-being deficits', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_MEAN')( - outcome, - ) - const EXPECTED_MEAN_SCORE = 0.5 - expect(result).toEqual(EXPECTED_MEAN_SCORE) - }) - - it('should return the expected raw for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_RAW')(outcome) - const EXPECTED_RAW_SCORE = 3 - - expect(result).toEqual(EXPECTED_RAW_SCORE) - }) - - it('should return the expected mean score for Problems/symptoms', function () { - const result = view_result('PROBLEMS_SYMPTOMS_MEAN')(outcome) - const EXPECTED_MEAN_SCORE = 0.25 - - expect(result).toEqual(EXPECTED_MEAN_SCORE) - }) - - it('should return the expected raw score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_RAW')(outcome) - const EXPECTED_RAW_SCORE = 22 - - expect(result).toEqual(EXPECTED_RAW_SCORE) - }) - - it('should return the expected mean score for Life functioning difficulties', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_MEAN')( - outcome, - ) - const EXPECTED_MEAN_SCORE = 1.83 - - expect(result).toEqual(EXPECTED_MEAN_SCORE) - }) - - it('should return the expected raw score for Risk/harm', function () { - const result = view_result('RISK_HARM_RAW')(outcome) - const EXPECTED_RAW_SCORE = 1 - - expect(result).toEqual(EXPECTED_RAW_SCORE) - }) - - it('should return the expected mean score for Risk/harm', function () { - const result = view_result('RISK_HARM_MEAN')(outcome) - const EXPECTED_MEAN_SCORE = 0.17 - - expect(result).toEqual(EXPECTED_MEAN_SCORE) - }) - - it('should return the expected raw score for Total', function () { - const result = view_result('TOTAL_RAW')(outcome) - const EXPECTED_RAW_SCORE = 28 - - expect(result).toEqual(EXPECTED_RAW_SCORE) - }) - - it('should return the expected mean score for Total', function () { - const result = view_result('TOTAL_MEAN')(outcome) - const EXPECTED_MEAN_SCORE = 0.82 - - expect(result).toEqual(EXPECTED_MEAN_SCORE) - }) - }) - }) - - describe('a score is only calculated when all mandatory fields are entered', function () { - describe('when an empty response is passed', function () { - const outcome = core_om_calculation({}) - - describe('For the Subjective well-being deficits raw score', function () { - it('should return undefined result ', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_RAW')( - outcome, - ) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('SUBJECTIVE_WELL_BEING_DEFICITS_RAW')( - outcome, - ) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Subjective well-being deficits mean score', function () { - it('should return undefined result ', function () { - const result = view_result('SUBJECTIVE_WELL_BEING_DEFICITS_MEAN')( - outcome, - ) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('SUBJECTIVE_WELL_BEING_DEFICITS_MEAN')( - outcome, - ) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Problems/symptoms raw score"', function () { - it('should return undefined result ', function () { - const result = view_result('PROBLEMS_SYMPTOMS_RAW')(outcome) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('PROBLEMS_SYMPTOMS_RAW')(outcome) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Problems/symptoms mean score', function () { - it('should return undefined result ', function () { - const result = view_result('PROBLEMS_SYMPTOMS_MEAN')(outcome) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('PROBLEMS_SYMPTOMS_MEAN')(outcome) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Life functioning difficulties raw score"', function () { - it('should return undefined result ', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_RAW')( - outcome, - ) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('LIFE_FUNCTIONING_DIFFICULTIES_RAW')( - outcome, - ) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Life functioning difficulties mean score', function () { - it('should return undefined result ', function () { - const result = view_result('LIFE_FUNCTIONING_DIFFICULTIES_MEAN')( - outcome, - ) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('LIFE_FUNCTIONING_DIFFICULTIES_MEAN')( - outcome, - ) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Risk/harm raw score"', function () { - it('should return undefined result ', function () { - const result = view_result('RISK_HARM_RAW')(outcome) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('RISK_HARM_RAW')(outcome) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Risk/harm mean score', function () { - it('should return undefined result ', function () { - const result = view_result('RISK_HARM_MEAN')(outcome) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('RISK_HARM_MEAN')(outcome) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Total raw score"', function () { - it('should return undefined result ', function () { - const result = view_result('TOTAL_RAW')(outcome) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('TOTAL_RAW')(outcome) - expect(status).toEqual(MISSING_STATUS) - }) - }) - - describe('For the Total mean score', function () { - it('should return undefined result ', function () { - const result = view_result('TOTAL_MEAN')(outcome) - expect(result).toEqual(undefined) - }) - - it('should return missing status ', function () { - const status = view_status('TOTAL_MEAN')(outcome) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - }) - - describe('values entered by the user are checked to verify they are inside specified ranges', function () { - describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - core_om_calculation({ - CORE_OM_Q01: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - core_om_calculation({ - CORE_OM_Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - core_om_calculation({ - CORE_OM_Q01: 6, - }), - ).toThrow(InvalidInputsError) - }) - }) - }) -}) diff --git a/todo/core_om/core_om.ts b/todo/core_om/core_om.ts deleted file mode 100644 index 2a3cc09..0000000 --- a/todo/core_om/core_om.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { add_raw_values_to_inputs } from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { - CORE_OM_INPUTS, - CORE_OM_OUTPUT, - CORE_OM_SUBSCALE_ITEMS, -} from './definition' -import { calculate_mean_score, calculate_raw_score } from './helpers' - -const calculate_core_om_scores = ( - calculation_input: Array, -): WIPCalculationResultType => [ - { - id: 'SUBJECTIVE_WELL_BEING_DEFICITS_RAW', - score: calculate_raw_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.SUBJECTIVE_WELLBEING, - ), - }, - { - id: 'SUBJECTIVE_WELL_BEING_DEFICITS_MEAN', - score: calculate_mean_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.SUBJECTIVE_WELLBEING, - ), - }, - { - id: 'PROBLEMS_SYMPTOMS_RAW', - score: calculate_raw_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.PROBLEMS_SYMPTOMS, - ), - }, - { - id: 'PROBLEMS_SYMPTOMS_MEAN', - score: calculate_mean_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.PROBLEMS_SYMPTOMS, - ), - }, - { - id: 'LIFE_FUNCTIONING_DIFFICULTIES_RAW', - score: calculate_raw_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.LIFE_FUNCTIONING_DIFFICULTIES, - ), - }, - { - id: 'LIFE_FUNCTIONING_DIFFICULTIES_MEAN', - score: calculate_mean_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.LIFE_FUNCTIONING_DIFFICULTIES, - ), - }, - { - id: 'RISK_HARM_RAW', - score: calculate_raw_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.RISK_HARM, - ), - }, - { - id: 'RISK_HARM_MEAN', - score: calculate_mean_score(calculation_input)( - CORE_OM_SUBSCALE_ITEMS.RISK_HARM, - ), - }, - { - id: 'TOTAL_RAW', - score: calculate_raw_score(calculation_input)([ - ...CORE_OM_SUBSCALE_ITEMS.SUBJECTIVE_WELLBEING, - ...CORE_OM_SUBSCALE_ITEMS.RISK_HARM, - ...CORE_OM_SUBSCALE_ITEMS.LIFE_FUNCTIONING_DIFFICULTIES, - ...CORE_OM_SUBSCALE_ITEMS.PROBLEMS_SYMPTOMS, - ]), - }, - { - id: 'TOTAL_MEAN', - score: calculate_mean_score(calculation_input)([ - ...CORE_OM_SUBSCALE_ITEMS.SUBJECTIVE_WELLBEING, - ...CORE_OM_SUBSCALE_ITEMS.RISK_HARM, - ...CORE_OM_SUBSCALE_ITEMS.LIFE_FUNCTIONING_DIFFICULTIES, - ...CORE_OM_SUBSCALE_ITEMS.PROBLEMS_SYMPTOMS, - ]), - }, -] - -export const specific_steps_core_om_calc = [ - calculate_core_om_scores, - add_raw_values_to_inputs(CORE_OM_INPUTS), -] - -export const core_om: CalculationType = create_calculation({ - calculation_name: 'Clinical Outcomes in Routine Evaluation (CORE-OM)', - readme_location: __dirname, - calculation_steps: specific_steps_core_om_calc, - calculation_definition: { - input_definition: CORE_OM_INPUTS, - output_definition: CORE_OM_OUTPUT, - }, -}) diff --git a/todo/core_om/definition/core_om_output.ts b/todo/core_om/definition/core_om_output.ts deleted file mode 100644 index 36f26b7..0000000 --- a/todo/core_om/definition/core_om_output.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const CORE_OM_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'SUBJECTIVE_WELL_BEING_DEFICITS_RAW', - label: { en: 'Subjective well-being deficits - Raw Score' }, - type: 'number', - }, - { - subresult_id: 'SUBJECTIVE_WELL_BEING_DEFICITS_MEAN', - label: { en: 'Subjective well-being deficits - Mean Score' }, - type: 'number', - }, - { - subresult_id: 'PROBLEMS_SYMPTOMS_RAW', - label: { en: 'Problems/symptoms - Raw Score' }, - type: 'number', - }, - { - subresult_id: 'PROBLEMS_SYMPTOMS_MEAN', - label: { en: 'Problems/symptoms - Mean Score' }, - type: 'number', - }, - { - subresult_id: 'LIFE_FUNCTIONING_DIFFICULTIES_RAW', - label: { en: 'Life functioning difficulties - Raw Score' }, - type: 'number', - }, - { - subresult_id: 'LIFE_FUNCTIONING_DIFFICULTIES_MEAN', - label: { en: 'Life functioning difficulties - Mean Score' }, - type: 'number', - }, - { - subresult_id: 'RISK_HARM_RAW', - label: { en: 'Risk/harm - Raw Score' }, - type: 'number', - }, - { - subresult_id: 'RISK_HARM_MEAN', - label: { en: 'Risk/harm - Mean Score' }, - type: 'number', - }, - { - subresult_id: 'TOTAL_RAW', - label: { en: 'Total - Raw Score' }, - type: 'number', - }, - { - subresult_id: 'TOTAL_MEAN', - label: { en: 'Total - Mean Score' }, - type: 'number', - }, -] diff --git a/todo/core_om/helpers/calculate_mean_score.ts b/todo/core_om/helpers/calculate_mean_score.ts deleted file mode 100644 index 1243f97..0000000 --- a/todo/core_om/helpers/calculate_mean_score.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { round } from 'mathjs' -import R from 'ramda' - -import type { InputType } from '../../../src/types/calculations.types' -import { - inputIdLens, - rawInputValueLens, -} from '../../../lib/calculation_variants/api/input/lenses' -import { MISSING_MESSAGE } from '../../../PARAMETERS' -import { is_numeric } from '../../../src/calculation_suite/calculations/shared_functions' - -export const calculate_mean_score = - (calculation_input: Array) => - (input_ids: string[]): number | string => { - const valid_inputs = R.compose( - R.filter(is_numeric), - R.map(input => R.view(rawInputValueLens, input)), - R.filter(input => input_ids.includes(R.view(inputIdLens, input))), - )(calculation_input) - - if (valid_inputs.length === 0) return MISSING_MESSAGE - - const ROUND_TO = 2 - - return round(R.sum(valid_inputs) / valid_inputs.length, ROUND_TO) - } diff --git a/todo/core_om/helpers/calculate_raw_score.ts b/todo/core_om/helpers/calculate_raw_score.ts deleted file mode 100644 index 4f0494b..0000000 --- a/todo/core_om/helpers/calculate_raw_score.ts +++ /dev/null @@ -1,23 +0,0 @@ -import R from 'ramda' - -import type { InputType } from '../../../src/types/calculations.types' -import { - inputIdLens, - rawInputValueLens, -} from '../../../lib/calculation_variants/api/input/lenses' -import { MISSING_MESSAGE } from '../../../PARAMETERS' -import { is_numeric } from '../../../src/calculation_suite/calculations/shared_functions' - -export const calculate_raw_score = - (calculation_input: Array) => - (input_ids: string[]): number | string => { - const valid_inputs = R.compose( - R.filter(is_numeric), - R.map(input => R.view(rawInputValueLens, input)), - R.filter(input => input_ids.includes(R.view(inputIdLens, input))), - )(calculation_input) - - if (valid_inputs.length === 0) return MISSING_MESSAGE - - return R.sum(valid_inputs) - } diff --git a/todo/core_om/helpers/index.ts b/todo/core_om/helpers/index.ts deleted file mode 100644 index ad73d25..0000000 --- a/todo/core_om/helpers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { calculate_raw_score } from './calculate_raw_score' -export { calculate_mean_score } from './calculate_mean_score' diff --git a/todo/csi/csi.test.ts b/todo/csi/csi.test.ts index b7a4149..458bd1d 100644 --- a/todo/csi/csi.test.ts +++ b/todo/csi/csi.test.ts @@ -84,31 +84,31 @@ describe('csi', function () { describe('when called with a response with answers out of the expected [0,4] range', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => csi_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => csi_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => csi_calculation({ Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/dlqi/dlqi.test.ts b/todo/dlqi/dlqi.test.ts index 8b2a453..904543c 100644 --- a/todo/dlqi/dlqi.test.ts +++ b/todo/dlqi/dlqi.test.ts @@ -516,30 +516,30 @@ describe('dlqi', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dlqi_calculation({ DLQI_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dlqi_calculation({ DLQI_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dlqi_calculation({ DLQI_Q01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/dri/dri.test.ts b/todo/dri/dri.test.ts index 6305e33..1889fd6 100644 --- a/todo/dri/dri.test.ts +++ b/todo/dri/dri.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -241,30 +241,30 @@ describe('dri', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dri_calculation({ DRI_01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dri_calculation({ DRI_01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => dri_calculation({ DRI_01: 110, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/eortc/eortc_qlq_br23/eortc_qlq_br23.test.ts b/todo/eortc/eortc_qlq_br23/eortc_qlq_br23.test.ts index b7f7c10..435516c 100644 --- a/todo/eortc/eortc_qlq_br23/eortc_qlq_br23.test.ts +++ b/todo/eortc/eortc_qlq_br23/eortc_qlq_br23.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -61,32 +61,32 @@ describe('eortc_qlq_br23', function () { describe('validation', function () { describe('values entered by the user shall be checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_br23_calculation({ EORTC_QLQ_BR23_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_br23_calculation({ EORTC_QLQ_BR23_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_br23_calculation({ EORTC_QLQ_BR23_Q01: 999, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/eortc/eortc_qlq_c30/eortc_qlq_c30.test.ts b/todo/eortc/eortc_qlq_c30/eortc_qlq_c30.test.ts index db94fef..a5757ff 100644 --- a/todo/eortc/eortc_qlq_c30/eortc_qlq_c30.test.ts +++ b/todo/eortc/eortc_qlq_c30/eortc_qlq_c30.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import { round } from 'mathjs' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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 { CALCULATIONS } from '../../calculation_library' @@ -464,30 +464,30 @@ describe('eortc_qlq_c30', function () { describe('values entered by the user shall be checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_c30_calculation({ EORTCQLQC30_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_c30_calculation({ EORTCQLQC30_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_c30_calculation({ EORTCQLQC30_Q01: 999, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/eortc/eortc_qlq_cr29/eortc_qlq_cr29.test.ts b/todo/eortc/eortc_qlq_cr29/eortc_qlq_cr29.test.ts index 2c8bef1..86e6a0a 100644 --- a/todo/eortc/eortc_qlq_cr29/eortc_qlq_cr29.test.ts +++ b/todo/eortc/eortc_qlq_cr29/eortc_qlq_cr29.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -2060,7 +2060,7 @@ describe('eortc_qlq_cr29', function () { eortc_qlq_cr29_calculation({ EORTCQLQCR29_Q31: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [1,4] range', function () { @@ -2069,7 +2069,7 @@ describe('eortc_qlq_cr29', function () { eortc_qlq_cr29_calculation({ EORTCQLQCR29_Q31: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [1,4] range', function () { @@ -2078,7 +2078,7 @@ describe('eortc_qlq_cr29', function () { eortc_qlq_cr29_calculation({ EORTCQLQCR29_Q31: 999, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/eortc/eortc_qlq_lc13/eortc_qlq_lc13.test.ts b/todo/eortc/eortc_qlq_lc13/eortc_qlq_lc13.test.ts index aae1e75..6f59d07 100644 --- a/todo/eortc/eortc_qlq_lc13/eortc_qlq_lc13.test.ts +++ b/todo/eortc/eortc_qlq_lc13/eortc_qlq_lc13.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -260,30 +260,30 @@ describe('eortc_qlq_lc13', function () { describe('values entered by the user shall be checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_lc13_calculation({ EORTCQLQLC13_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_lc13_calculation({ EORTCQLQLC13_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_lc13_calculation({ EORTCQLQLC13_Q01: 999, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/eortc/eortc_qlq_lc29/eortc_qlq_lc29.test.ts b/todo/eortc/eortc_qlq_lc29/eortc_qlq_lc29.test.ts index c4cda12..c33e2a0 100644 --- a/todo/eortc/eortc_qlq_lc29/eortc_qlq_lc29.test.ts +++ b/todo/eortc/eortc_qlq_lc29/eortc_qlq_lc29.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../src/calculation_suite/errors' +import { ZodError } from '../../../src/calculation_suite/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' @@ -272,30 +272,30 @@ describe('eortc_qlq_lc29', function () { describe('values entered by the user shall be checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_lc29_calculation({ EORTC_QLQ_LC29_Q31: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_lc29_calculation({ EORTC_QLQ_LC29_Q31: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [1,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_lc29_calculation({ EORTC_QLQ_LC29_Q31: 999, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/eortc/eortc_qlq_pr25/eortc_qlq_pr25.test.ts b/todo/eortc/eortc_qlq_pr25/eortc_qlq_pr25.test.ts index be1b183..8a6398c 100644 --- a/todo/eortc/eortc_qlq_pr25/eortc_qlq_pr25.test.ts +++ b/todo/eortc/eortc_qlq_pr25/eortc_qlq_pr25.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -326,30 +326,30 @@ describe('eortc_qlq_pr25', function () { describe('values entered by the user shall be checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_pr25_calculation({ EORTC_QLQ_PR25_Q31: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_pr25_calculation({ EORTC_QLQ_PR25_Q31: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => eortc_qlq_pr25_calculation({ EORTC_QLQ_PR25_Q31: 999, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/epic_26/epic_26.test.ts b/todo/epic_26/epic_26.test.ts index 496d4ad..f93019f 100644 --- a/todo/epic_26/epic_26.test.ts +++ b/todo/epic_26/epic_26.test.ts @@ -239,30 +239,30 @@ describe('epic_26', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => epic_26_calculation({ EPIC26_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => epic_26_calculation({ EPIC26_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => epic_26_calculation({ EPIC26_Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/ess/definition/ess_inputs.ts b/todo/ess/definition/ess_inputs.ts deleted file mode 100644 index 434ff75..0000000 --- a/todo/ess/definition/ess_inputs.ts +++ /dev/null @@ -1,108 +0,0 @@ -import type { InputType } from '../../../src/types/calculations.types' -import { NumberInputType } from '../../../src/types/calculations/inputs/calculation-inputs.types' - -const type: NumberInputType = { - type: 'number', - allowed_answers: [ - { - value: 0, - label: { nl: 'Ik word niet doezelig/slaperig', en: 'Would never dose' }, - }, - { - value: 1, - label: { - nl: 'Lichte kans dat ik doezelig/slaperig word', - en: 'Slight chance of dozing', - }, - }, - { - value: 2, - label: { - nl: 'Matige kans dat ik doezelig/slaperig word', - en: 'Moderate chance of dozing', - }, - }, - { - value: 3, - label: { - nl: 'Hoge kans dat ik doezelig/slaperig word', - en: 'High chance of dozing', - }, - }, - ], -} - -export const ESS_INPUTS: Array = [ - { - input_id: 'ESS_Q1', - label: { - nl: 'Tijdens zitten en lezen', - en: 'Sitting and reading', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q2', - label: { - nl: 'Tijdens televisie kijken', - en: 'Watching TV', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q3', - label: { - nl: 'Zitten in een openbare instelling (zoals theater)', - en: 'Sitting still in a public place (e.g. a theatre, a cinema or a meeting)', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q4', - label: { - nl: 'Langer dan 1 uur zittend als passagier in de auto', - en: 'As a passenger in a car for an hour without a break', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q5', - label: { - nl: 'Tijdens rust in de namiddag ', - en: 'Lying down to rest in the afternoon when the circumstances allow', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q6', - label: { - nl: 'Zitten en praten met iemand', - en: 'Sitting and talking to someone', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q7', - label: { - nl: 'Na de lunch', - en: 'Sitting quietly after lunch without having drunk alcohol', - }, - input_type, - required: true, - }, - { - input_id: 'ESS_Q8', - label: { - nl: 'In de auto in een stilstaande file', - en: 'In a car or bus while stopped for a few minutes in traffic', - }, - input_type, - required: true, - }, -] diff --git a/todo/ess/definition/ess_output.ts b/todo/ess/definition/ess_output.ts deleted file mode 100644 index dcf8f23..0000000 --- a/todo/ess/definition/ess_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const ESS_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'ess', - label: { en: 'Total ESS score' }, - type: 'number', - }, -] diff --git a/todo/ess/ess.test.ts b/todo/ess/ess.test.ts deleted file mode 100644 index 24affc3..0000000 --- a/todo/ess/ess.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { expect } from 'chai' -import { compose } from 'ramda' - -import { Score } from '../../classes' -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 { ScoreLibrary } from '../library' -import { get_input_ids_from_calculation_blueprint } from '../../src/calculation_suite/calculations/shared_functions' -import { - max_response, - median_response, - min_response, - random_response, -} from './__testdata__/ess_test_responses' -import { ESS_INPUTS } from './definition/ess_inputs' -// eslint-disable-next-line sort-imports -import { ess, ESSCalculationName } from './ess' - -const ESS_MIN_SCORE = 0 -const ESS_MID_SCORE = 12 -const ESS_MAX_SCORE = 24 - -const ess_calculation = execute_test_calculation(ess) - -describe('ess', function () { - it('ess calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('ess') - }) - - describe('basic assumptions', function () { - const outcome = ess_calculation(min_response) - - it('should return 1 calculation result', function () { - expect(outcome).toHaveLength(1) - }) - - it('should have the expected calculation id', function () { - const EXPECTED_CALCULATION_ID = ['ess'] - 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 = [ - 'ESS_Q1', - 'ESS_Q2', - 'ESS_Q3', - 'ESS_Q4', - 'ESS_Q5', - 'ESS_Q6', - 'ESS_Q7', - 'ESS_Q8', - ] - - const configured_input_ids = - get_input_ids_from_calculation_blueprint(ESS_INPUTS) - - expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) - }) - }) - describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ess_calculation({ - ESS_Q1: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with a response where there are answers out of the expected [0, 4] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ess_calculation({ - ESS_Q1: 5, - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when called with a response where there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ess_calculation({ - ESS_Q1: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - describe('when called with an empty response', function () { - it('should return undefined result as score', function () { - const score = compose( - view_result(ESSCalculationName), - ess_calculation, - )({}) - - expect(score).toEqual(undefined) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with a minimum response', function () { - it('should return the minimum score', function () { - const score = compose( - view_result(ESSCalculationName), - ess_calculation, - )(min_response) - - expect(score).toEqual(ESS_MIN_SCORE) - }) - }) - - describe('when called with a median response', function () { - it('should return the median score', function () { - const score = compose( - view_result(ESSCalculationName), - ess_calculation, - )(median_response) - - expect(score).toEqual(ESS_MID_SCORE) - }) - }) - - describe('when called with a maximum response', function () { - it('should return the maximum score', function () { - const score = compose( - view_result(ESSCalculationName), - ess_calculation, - )(max_response) - - expect(score).toEqual(ESS_MAX_SCORE) - }) - }) - - describe('when called with a random response', function () { - it('should return the expected score', function () { - const score = compose( - view_result(ESSCalculationName), - ess_calculation, - )(random_response) - - const EXPECTED_SCORE = 13 - - expect(score).toEqual(EXPECTED_SCORE) - }) - }) - }) -}) diff --git a/todo/ess/ess.ts b/todo/ess/ess.ts deleted file mode 100644 index d1b57af..0000000 --- a/todo/ess/ess.ts +++ /dev/null @@ -1,54 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { - add_raw_values_to_inputs, - do_all_required_inputs_have_a_valid_value, - get_valid_values, -} from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../PARAMETERS' -import { ESS_INPUTS, ESS_OUTPUT } from './definition' - -export const ESSCalculationName = 'ess' - -const calculate_ess_score = ( - cpdi_inputs_with_answers: Array, -): WIPCalculationResultType => { - if (do_all_required_inputs_have_a_valid_value(cpdi_inputs_with_answers)) { - const total_score = R.sum(get_valid_values(cpdi_inputs_with_answers)) - - return [ - { - id: ESSCalculationName, - score: total_score, - }, - ] - } - - return [ - { - id: ESSCalculationName, - score: MISSING_MESSAGE, - }, - ] -} - -export const specific_steps_ess_calc = [ - calculate_ess_score, - add_raw_values_to_inputs(ESS_INPUTS), -] - -export const ess: CalculationType = create_calculation({ - calculation_name: `Epworth Sleepiness Scale (ESS)`, - readme_location: __dirname, - calculation_steps: specific_steps_ess_calc, - calculation_definition: { - input_definition: ESS_INPUTS, - output_definition: ESS_OUTPUT, - }, -}) diff --git a/todo/faam/faam.test.ts b/todo/faam/faam.test.ts index 061d2c5..775f688 100644 --- a/todo/faam/faam.test.ts +++ b/todo/faam/faam.test.ts @@ -225,7 +225,7 @@ describe('faam', function () { faam_calculation({ ADL_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -234,7 +234,7 @@ describe('faam', function () { faam_calculation({ ADL_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -243,7 +243,7 @@ describe('faam', function () { faam_calculation({ ADL_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/fes_i/short_version/short_fes_i.test.ts b/todo/fes_i/short_version/short_fes_i.test.ts index d919c83..fd9304f 100644 --- a/todo/fes_i/short_version/short_fes_i.test.ts +++ b/todo/fes_i/short_version/short_fes_i.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -61,12 +61,12 @@ describe('short_fes_i', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => short_fes_i_calculation({ Q01: 0, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/foot_function_index/5pt_version/foot_function_index_5pt.test.ts b/todo/foot_function_index/5pt_version/foot_function_index_5pt.test.ts index ab24dd9..5645092 100644 --- a/todo/foot_function_index/5pt_version/foot_function_index_5pt.test.ts +++ b/todo/foot_function_index/5pt_version/foot_function_index_5pt.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -283,30 +283,30 @@ describe('foot_function_index_5pt', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ffi_calculation({ DISABILITY_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ffi_calculation({ DISABILITY_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ffi_calculation({ DISABILITY_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_output.ts b/todo/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_output.ts deleted file mode 100644 index b3a528d..0000000 --- a/todo/forgotten_joint_score_12/hip/definition/forgotten_joint_score_12_hip_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../../src/types/calculations.types' - -export const FJS_HIP_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'FORGOTTEN_JOINT_SCORE_HIP', - label: { en: 'Forgotten Joint Score - Hip' }, - type: 'number', - }, -] diff --git a/todo/forgotten_joint_score_12/hip/forgotten_joint_score_12_hip.test.ts b/todo/forgotten_joint_score_12/hip/forgotten_joint_score_12_hip.test.ts deleted file mode 100644 index 5c2ee23..0000000 --- a/todo/forgotten_joint_score_12/hip/forgotten_joint_score_12_hip.test.ts +++ /dev/null @@ -1,155 +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, - median_response, - random_response, - worst_response, -} from './__testdata__/forgotten_joint_score_12_hip_test_responses' -import { FJS_HIP_INPUTS } from './definition' -import { forgotten_joint_score_hip } from './forgotten_joint_score_hip_12' - -const BEST_FJS_SCORE = 100 -const MEDIAN_FJS_SCORE = 50 -const WORST_FJS_SCORE = 0 - -const fjs_calculation = execute_test_calculation(forgotten_joint_score_hip) - -describe('forgotten_joint_score_hip', function () { - it('forgotten_joint_score_hip calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('forgotten_joint_score_hip') - }) - - describe('basic assumptions', function () { - const outcome = fjs_calculation(best_response) - - it('should return 1 calculation result', function () { - expect(outcome).toHaveLength(1) - }) - - it('should have the expected calculation result id', function () { - const EXPECTED_CALCULATION_ID = ['FORGOTTEN_JOINT_SCORE_HIP'] - - 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 = [ - 'Q01', - 'Q02', - 'Q03', - 'Q04', - 'Q05', - 'Q06', - 'Q07', - 'Q08', - 'Q09', - 'Q10', - 'Q11', - 'Q12', - ] - - const configured_input_ids = - get_input_ids_from_calculation_blueprint(FJS_HIP_INPUTS) - - expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) - }) - }) - - describe('when an answer is below the expected [1,5] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - fjs_calculation({ - Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with a response where there are answers out of the expected [1, 5] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - fjs_calculation({ - Q01: 6, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with a response where there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - fjs_calculation({ - Q01: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with an empty response', function () { - it('should return undefined result as the score and a missing status', function () { - const outcome = fjs_calculation({}) - - const score = view_result('FORGOTTEN_JOINT_SCORE_HIP')(outcome) - const status = view_status('FORGOTTEN_JOINT_SCORE_HIP')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with the best response', function () { - it('should return the best FJS score', function () { - const outcome = fjs_calculation(best_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_HIP')(outcome) - - expect(score).toEqual(BEST_FJS_SCORE) - }) - }) - - describe('when called with the median response', function () { - it('should return the median FJS score', function () { - const outcome = fjs_calculation(median_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_HIP')(outcome) - - expect(score).toEqual(MEDIAN_FJS_SCORE) - }) - }) - - describe('when called with the worst response', function () { - it('should return the worst FJS score', function () { - const outcome = fjs_calculation(worst_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_HIP')(outcome) - - expect(score).toEqual(WORST_FJS_SCORE) - }) - }) - - describe('when called with a random response', function () { - it('should return the expected FJS score', function () { - const outcome = fjs_calculation(random_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_HIP')(outcome) - - const EXPECTED_SCORE = 65 - - expect(score).toEqual(EXPECTED_SCORE) - }) - }) - }) -}) diff --git a/todo/forgotten_joint_score_12/hip/forgotten_joint_score_hip_12.ts b/todo/forgotten_joint_score_12/hip/forgotten_joint_score_hip_12.ts deleted file mode 100644 index b3e00af..0000000 --- a/todo/forgotten_joint_score_12/hip/forgotten_joint_score_hip_12.ts +++ /dev/null @@ -1,81 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../../src/types/calculations.types' -import { - add_raw_values_to_inputs, - get_valid_values, -} from '../../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../../PARAMETERS' -import { FJS_HIP_INPUTS, FJS_HIP_OUTPUT } from './definition' - -const calculate_fjs_12_score = ( - inputs_with_answers: Array, -): WIPCalculationResultType => { - const valid_answer_values = get_valid_values(inputs_with_answers) - const MAX_INVALID_ANSWERS = 4 - const TOTAL_AMOUNT_OF_QUESTIONS = 12 - - const nbr_of_valid_answered_questions = valid_answer_values.length - const nbr_of_invalid_answered_questions = - TOTAL_AMOUNT_OF_QUESTIONS - nbr_of_valid_answered_questions - - /** - * If more than four of the answers are missing then the - * total score should be treated as missing. - */ - if (nbr_of_invalid_answered_questions > MAX_INVALID_ANSWERS) - return [ - { - id: 'FORGOTTEN_JOINT_SCORE_HIP', - score: MISSING_MESSAGE, - }, - ] - - /** - * In case of missing answers (<= 4), the mean of the answered items is used - * instead of the sum of all items and multiplied by 12 (i.e. the missing values are - * replaced with the mean of the completed items). - */ - let wip_score - - if (nbr_of_valid_answered_questions === TOTAL_AMOUNT_OF_QUESTIONS) { - wip_score = R.sum(valid_answer_values) - } else { - wip_score = R.mean(valid_answer_values) * 12 - } - - const fjs_score = ((wip_score - 12) / 48) * 100 - - /** - * 0 = worst outcome - * 100 = best ourcome - */ - const reversed_fjs_score = 100 - fjs_score - - return [ - { - id: 'FORGOTTEN_JOINT_SCORE_HIP', - score: Math.round(reversed_fjs_score), - }, - ] -} - -export const specific_steps_fjs_12_hip_calc = [ - calculate_fjs_12_score, - add_raw_values_to_inputs(FJS_HIP_INPUTS), -] - -export const forgotten_joint_score_hip: CalculationType = create_calculation({ - calculation_name: 'Forgotten Joint Score – 12 (FJS-12) - Hip', - readme_location: __dirname, - calculation_steps: specific_steps_fjs_12_hip_calc, - calculation_definition: { - input_definition: FJS_HIP_INPUTS, - output_definition: FJS_HIP_OUTPUT, - }, -}) diff --git a/todo/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_output.ts b/todo/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_output.ts deleted file mode 100644 index 5ede387..0000000 --- a/todo/forgotten_joint_score_12/knee/definition/forgotten_joint_score_12_knee_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../../src/types/calculations.types' - -export const FJS_KNEE_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'FORGOTTEN_JOINT_SCORE_KNEE', - label: { en: 'Forgotten Joint Score - Knee' }, - type: 'number', - }, -] diff --git a/todo/forgotten_joint_score_12/knee/forgotten_joint_score_12_knee.test.ts b/todo/forgotten_joint_score_12/knee/forgotten_joint_score_12_knee.test.ts deleted file mode 100644 index 2b5a6e3..0000000 --- a/todo/forgotten_joint_score_12/knee/forgotten_joint_score_12_knee.test.ts +++ /dev/null @@ -1,155 +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, - median_response, - random_response, - worst_response, -} from './__testdata__/forgotten_joint_score_12_knee_test_responses' -import { FJS_KNEE_INPUTS } from './definition' -import { forgotten_joint_score_knee } from './forgotten_joint_score_knee_12' - -const BEST_FJS_SCORE = 100 -const MEDIAN_FJS_SCORE = 50 -const WORST_FJS_SCORE = 0 - -const fjs_calculation = execute_test_calculation(forgotten_joint_score_knee) - -describe('forgotten_joint_score_knee', function () { - it('forgotten_joint_score_knee calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('forgotten_joint_score_knee') - }) - - describe('basic assumptions', function () { - const outcome = fjs_calculation(best_response) - - it('should return 1 calculation result', function () { - expect(outcome).toHaveLength(1) - }) - - it('should have the expected calculation result id', function () { - const EXPECTED_CALCULATION_ID = ['FORGOTTEN_JOINT_SCORE_KNEE'] - - 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 = [ - 'Q01', - 'Q02', - 'Q03', - 'Q04', - 'Q05', - 'Q06', - 'Q07', - 'Q08', - 'Q09', - 'Q10', - 'Q11', - 'Q12', - ] - - const configured_input_ids = - get_input_ids_from_calculation_blueprint(FJS_KNEE_INPUTS) - - expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) - }) - }) - - describe('when an answer is below the expected [1,5] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - fjs_calculation({ - Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with a response where there are answers out of the expected [1, 5] range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - fjs_calculation({ - Q01: 6, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with a response where there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - fjs_calculation({ - Q01: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with an empty response', function () { - it('should return undefined result as the score and a missing status', function () { - const outcome = fjs_calculation({}) - - const score = view_result('FORGOTTEN_JOINT_SCORE_KNEE')(outcome) - const status = view_status('FORGOTTEN_JOINT_SCORE_KNEE')(outcome) - - expect(score).toEqual(undefined) - expect(status).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with the best response', function () { - it('should return the best FJS score', function () { - const outcome = fjs_calculation(best_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_KNEE')(outcome) - - expect(score).toEqual(BEST_FJS_SCORE) - }) - }) - - describe('when called with the median response', function () { - it('should return the median FJS score', function () { - const outcome = fjs_calculation(median_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_KNEE')(outcome) - - expect(score).toEqual(MEDIAN_FJS_SCORE) - }) - }) - - describe('when called with the worst response', function () { - it('should return the worst FJS score', function () { - const outcome = fjs_calculation(worst_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_KNEE')(outcome) - - expect(score).toEqual(WORST_FJS_SCORE) - }) - }) - - describe('when called with a random response', function () { - it('should return the expected FJS score', function () { - const outcome = fjs_calculation(random_response) - const score = view_result('FORGOTTEN_JOINT_SCORE_KNEE')(outcome) - - const EXPECTED_SCORE = 65 - - expect(score).toEqual(EXPECTED_SCORE) - }) - }) - }) -}) diff --git a/todo/forgotten_joint_score_12/knee/forgotten_joint_score_knee_12.ts b/todo/forgotten_joint_score_12/knee/forgotten_joint_score_knee_12.ts deleted file mode 100644 index 6648bb1..0000000 --- a/todo/forgotten_joint_score_12/knee/forgotten_joint_score_knee_12.ts +++ /dev/null @@ -1,81 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../../src/types/calculations.types' -import { - add_raw_values_to_inputs, - get_valid_values, -} from '../../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../../PARAMETERS' -import { FJS_KNEE_INPUTS, FJS_KNEE_OUTPUT } from './definition' - -const calculate_fjs_12_score = ( - inputs_with_answers: Array, -): WIPCalculationResultType => { - const valid_answer_values = get_valid_values(inputs_with_answers) - const MAX_INVALID_ANSWERS = 4 - const TOTAL_AMOUNT_OF_QUESTIONS = 12 - - const nbr_of_valid_answered_questions = valid_answer_values.length - const nbr_of_invalid_answered_questions = - TOTAL_AMOUNT_OF_QUESTIONS - nbr_of_valid_answered_questions - - /** - * If more than four of the answers are missing then the - * total score should be treated as missing. - */ - if (nbr_of_invalid_answered_questions > MAX_INVALID_ANSWERS) - return [ - { - id: 'FORGOTTEN_JOINT_SCORE_KNEE', - score: MISSING_MESSAGE, - }, - ] - - /** - * In case of missing answers (<= 4), the mean of the answered items is used - * instead of the sum of all items and multiplied by 12 (i.e. the missing values are - * replaced with the mean of the completed items). - */ - let wip_score - - if (nbr_of_valid_answered_questions === TOTAL_AMOUNT_OF_QUESTIONS) { - wip_score = R.sum(valid_answer_values) - } else { - wip_score = R.mean(valid_answer_values) * 12 - } - - const fjs_score = ((wip_score - 12) / 48) * 100 - - /** - * 0 = worst outcome - * 100 = best ourcome - */ - const reversed_fjs_score = 100 - fjs_score - - return [ - { - id: 'FORGOTTEN_JOINT_SCORE_KNEE', - score: Math.round(reversed_fjs_score), - }, - ] -} - -export const specific_steps_fjs_12_knee_calc = [ - calculate_fjs_12_score, - add_raw_values_to_inputs(FJS_KNEE_INPUTS), -] - -export const forgotten_joint_score_knee: CalculationType = create_calculation({ - calculation_name: 'Forgotten Joint Score – 12 (FJS-12) - Knee', - readme_location: __dirname, - calculation_steps: specific_steps_fjs_12_knee_calc, - calculation_definition: { - input_definition: FJS_KNEE_INPUTS, - output_definition: FJS_KNEE_OUTPUT, - }, -}) diff --git a/todo/ghq_12/definition/ghq_12_output.ts b/todo/ghq_12/definition/ghq_12_output.ts deleted file mode 100644 index 02c0ee0..0000000 --- a/todo/ghq_12/definition/ghq_12_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const GHQ_12_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'GHQ_12_SCORING', - label: { en: 'GHQ Scoring' }, - type: 'number', - }, -] diff --git a/todo/ghq_12/ghq_12.test.ts b/todo/ghq_12/ghq_12.test.ts deleted file mode 100644 index b6720bf..0000000 --- a/todo/ghq_12/ghq_12.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { expect } from 'chai' -import R from 'ramda' - -import { Score } from '../../classes' -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 { ScoreLibrary } from '../library' -import { get_input_ids_from_calculation_blueprint } from '../../src/calculation_suite/calculations/shared_functions' -import { - best_response, - median_response, - random_response, - worst_response, -} from './__testdata__/ghq_12_test_responses' -import { GHQ_12_INPUTS } from './definition/ghq_12_inputs' -import { ghq_12 } from './ghq_12' - -const GHQ_12_BEST_SCORE = 0 -const GHQ_12_MEDIAN_SCORE = 6 -const GHQ_12_WORST_SCORE = 12 - -const ghq_12_calculation = execute_test_calculation(ghq_12) - -describe('ghq_12', function () { - it('ghq_12 calculation function should be available as a calculation', function () { - expect(CALCULATIONS).toHaveProperty('ghq_12') - }) - - describe('basic assumptions', function () { - const outcome = ghq_12_calculation(best_response) - - it('should return 1 calculation result', function () { - expect(outcome).toHaveLength(1) - }) - - it('should have the expected calculation id', function () { - const EXPECTED_CALCULATION_ID = ['GHQ_12_SCORING'] - 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 = [ - 'GHQ_12_Q01', - 'GHQ_12_Q02', - 'GHQ_12_Q03', - 'GHQ_12_Q04', - 'GHQ_12_Q05', - 'GHQ_12_Q06', - 'GHQ_12_Q07', - 'GHQ_12_Q08', - 'GHQ_12_Q09', - 'GHQ_12_Q10', - 'GHQ_12_Q11', - 'GHQ_12_Q12', - ] - - const configured_input_ids = - get_input_ids_from_calculation_blueprint(GHQ_12_INPUTS) - - expect(EXPECTED_INPUT_IDS).toEqual(configured_input_ids) - }) - }) - - describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ghq_12_calculation({ - GHQ_12_Q01: -1, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ghq_12_calculation({ - GHQ_12_Q01: 4, - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { - expect(() => - ghq_12_calculation({ - GHQ_12_Q01: "I'm not a number", - }), - ).toThrow(InvalidInputsError) - }) - }) - - describe('when called with an empty response', function () { - it('should return undefined result as the score', function () { - const score = R.compose( - view_result('GHQ_12_SCORING'), - ghq_12_calculation, - )({}) - - expect(score).toEqual(undefined) - }) - - it('should return MISSING as the status', function () { - const score = R.compose( - view_status('GHQ_12_SCORING'), - ghq_12_calculation, - )({}) - - expect(score).toEqual(MISSING_STATUS) - }) - }) - }) - - describe('score calculation', function () { - describe('when called with the worst response', function () { - it('should return the worst score', function () { - const score = R.compose( - view_result('GHQ_12_SCORING'), - ghq_12_calculation, - )(worst_response) - - expect(score).toEqual(GHQ_12_WORST_SCORE) - }) - }) - - describe('when called with a median response', function () { - it('should return the median score', function () { - const score = R.compose( - view_result('GHQ_12_SCORING'), - ghq_12_calculation, - )(median_response) - - expect(score).toEqual(GHQ_12_MEDIAN_SCORE) - }) - }) - - describe('when called with a maximum response', function () { - it('should return the maximum score', function () { - const score = R.compose( - view_result('GHQ_12_SCORING'), - ghq_12_calculation, - )(best_response) - - expect(score).toEqual(GHQ_12_BEST_SCORE) - }) - }) - - describe('when called with a random response', function () { - it('should return the expected score', function () { - const score = R.compose( - view_result('GHQ_12_SCORING'), - ghq_12_calculation, - )(random_response) - - const EXPECTED_SCORE = 9 - - expect(score).toEqual(EXPECTED_SCORE) - }) - }) - }) -}) diff --git a/todo/ghq_12/ghq_12.ts b/todo/ghq_12/ghq_12.ts deleted file mode 100644 index e0854f6..0000000 --- a/todo/ghq_12/ghq_12.ts +++ /dev/null @@ -1,63 +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 { GHQ_12_INPUTS, GHQ_12_OUTPUT } from './definition' - -const calculate_ghq_12_score = ( - ghq_12_inputs_with_answers: Array, -): WIPCalculationResultType => { - const valid_inputs = R.compose( - R.filter(is_numeric), - R.map(input => R.view(rawInputValueLens, input)), - )(ghq_12_inputs_with_answers) - - if (valid_inputs.length === 0) - return [ - { - id: 'GHQ_12_SCORING', - score: MISSING_MESSAGE, - }, - ] - - /** - * GHQ score is the sum of the amount of items that were scored 2 or 3 - */ - const DYSFUNCTIONAL_SCORES = [2, 3] - - const score = R.compose( - R.length, - //@ts-expect-error to do - R.filter(i => DYSFUNCTIONAL_SCORES.includes(i)), - )(valid_inputs) - - return [ - { - id: 'GHQ_12_SCORING', - score, - }, - ] -} - -export const specific_steps_ghq_12_calc = [ - calculate_ghq_12_score, - add_raw_values_to_inputs(GHQ_12_INPUTS), -] - -export const ghq_12: CalculationType = create_calculation({ - calculation_name: `The 12-Item General Health Questionnaire (GHQ-12)`, - readme_location: __dirname, - calculation_steps: specific_steps_ghq_12_calc, - calculation_definition: { - input_definition: GHQ_12_INPUTS, - output_definition: GHQ_12_OUTPUT, - }, -}) diff --git a/todo/hads/HADS_score.test.ts b/todo/hads/HADS_score.test.ts index 48df565..23a4c7f 100644 --- a/todo/hads/HADS_score.test.ts +++ b/todo/hads/HADS_score.test.ts @@ -112,21 +112,21 @@ describe('hads', function () { describe('when called with a response where there are answers out of the expected [0-3] range', function () { describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hads_calculation({ HADS_01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hads_calculation({ HADS_01: 4, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/harris_hip_score/harris_hip_score.test.ts b/todo/harris_hip_score/harris_hip_score.test.ts index 0cc5f09..07cbdd7 100644 --- a/todo/harris_hip_score/harris_hip_score.test.ts +++ b/todo/harris_hip_score/harris_hip_score.test.ts @@ -74,31 +74,31 @@ describe('harris_hip_score', function () { }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => harris_hip_score_calculation({ PAIN: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when called with a response where there are answers out of the expected [0, 4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => harris_hip_score_calculation({ PAIN: 100, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when called with a response where there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => harris_hip_score_calculation({ PAIN: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when called with an empty response', function () { diff --git a/todo/hoos_extended/hoos_extended.test.ts b/todo/hoos_extended/hoos_extended.test.ts index 78111e0..4b2b74a 100644 --- a/todo/hoos_extended/hoos_extended.test.ts +++ b/todo/hoos_extended/hoos_extended.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -367,7 +367,7 @@ describe('hoos_extended', function () { hoos_calculation({ a1: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -376,7 +376,7 @@ describe('hoos_extended', function () { hoos_calculation({ a1: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -385,7 +385,7 @@ describe('hoos_extended', function () { hoos_calculation({ a1: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/hos/hos.test.ts b/todo/hos/hos.test.ts index 10170e9..fe6bcb3 100644 --- a/todo/hos/hos.test.ts +++ b/todo/hos/hos.test.ts @@ -247,7 +247,7 @@ describe('hos', function () { hos_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -256,7 +256,7 @@ describe('hos', function () { hos_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -265,7 +265,7 @@ describe('hos', function () { hos_calculation({ Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/hrqol/hrqol_4/hrqol_4.test.ts b/todo/hrqol/hrqol_4/hrqol_4.test.ts index 6d527a0..04d02e3 100644 --- a/todo/hrqol/hrqol_4/hrqol_4.test.ts +++ b/todo/hrqol/hrqol_4/hrqol_4.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -349,30 +349,30 @@ describe('hrqol_4', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hrqol_4_calculation({ HRQOL_4_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hrqol_4_calculation({ HRQOL_4_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => hrqol_4_calculation({ HRQOL_4_Q02: 31, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/ias/ias.test.ts b/todo/ias/ias.test.ts index b1b7536..02e46b4 100644 --- a/todo/ias/ias.test.ts +++ b/todo/ias/ias.test.ts @@ -218,30 +218,30 @@ describe('ias', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ias_calclation({ IAS_Q02: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ias_calclation({ IAS_Q02: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ias_calclation({ IAS_Q02: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/ibd_disk_total_score/definition/ibd_disk_output.ts b/todo/ibd_disk_total_score/definition/ibd_disk_output.ts deleted file mode 100644 index 0a58ffd..0000000 --- a/todo/ibd_disk_total_score/definition/ibd_disk_output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CalculationOutputDefinition } from '../../../src/types/calculations.types' - -export const IBD_DISK_OUTPUT: CalculationOutputDefinition[] = [ - { - subresult_id: 'IBD_DISK_TOTAL', - label: { en: 'IBD Disk total ' }, - type: 'number', - }, -] diff --git a/todo/ibd_disk_total_score/ibd_disk_total_score.ts b/todo/ibd_disk_total_score/ibd_disk_total_score.ts deleted file mode 100644 index 9166c43..0000000 --- a/todo/ibd_disk_total_score/ibd_disk_total_score.ts +++ /dev/null @@ -1,51 +0,0 @@ -import R from 'ramda' - -import type { - CalculationType, - InputType, - WIPCalculationResultType, -} from '../../src/types/calculations.types' -import { - add_raw_values_to_inputs, - do_all_required_inputs_have_a_valid_value, - get_valid_values, -} from '../../lib/calculation_variants/simple_calculation' -import { create_calculation } from '../../lib/create_calculation' -import { MISSING_MESSAGE } from '../../PARAMETERS' -import { IBD_DISK_INPUTS, IBD_DISK_OUTPUT } from './definition' - -const CALCULATION_NAME = 'IBD_DISK_TOTAL' - -const calculate_ibd_disk_total_score = ( - calculation_input: Array, -): WIPCalculationResultType => { - if (do_all_required_inputs_have_a_valid_value(calculation_input)) - return [ - { - id: CALCULATION_NAME, - score: R.sum(get_valid_values(calculation_input)), - }, - ] - - return [ - { - id: CALCULATION_NAME, - score: MISSING_MESSAGE, - }, - ] -} - -export const specific_steps_ibd_disk_calc = [ - calculate_ibd_disk_total_score, - add_raw_values_to_inputs(IBD_DISK_INPUTS), -] - -export const ibd_disk_total_score: CalculationType = create_calculation({ - calculation_name: `IBD Disk total score`, - readme_location: __dirname, - calculation_steps: specific_steps_ibd_disk_calc, - calculation_definition: { - input_definition: IBD_DISK_INPUTS, - output_definition: IBD_DISK_OUTPUT, - }, -}) diff --git a/todo/iief5/iief5.test.ts b/todo/iief5/iief5.test.ts index 14cd016..840cea4 100644 --- a/todo/iief5/iief5.test.ts +++ b/todo/iief5/iief5.test.ts @@ -65,12 +65,12 @@ describe('iief5', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => iief5_calculation({ IIEF5_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/ikdc/ikdc.test.ts b/todo/ikdc/ikdc.test.ts index be775cd..1cea75f 100644 --- a/todo/ikdc/ikdc.test.ts +++ b/todo/ikdc/ikdc.test.ts @@ -126,30 +126,30 @@ describe('ikdc', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ikdc_calculation({ IKDC_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ikdc_calculation({ IKDC_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ikdc_calculation({ IKDC_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/ipss/ipss.test.ts b/todo/ipss/ipss.test.ts index 5cd2085..08b98bc 100644 --- a/todo/ipss/ipss.test.ts +++ b/todo/ipss/ipss.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -115,30 +115,30 @@ describe('ipss', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ipss_calculation({ IPSS_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0, 5] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ipss_calculation({ IPSS_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0, 5] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ipss_calculation({ IPSS_Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/isi/isi.test.ts b/todo/isi/isi.test.ts index 61aab0d..194bfb2 100644 --- a/todo/isi/isi.test.ts +++ b/todo/isi/isi.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -62,32 +62,32 @@ describe('isi', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => isi_calculation({ ISI_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => isi_calculation({ ISI_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => isi_calculation({ ISI_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/k_bild/k_bild.test.ts b/todo/k_bild/k_bild.test.ts index 4a5a203..9940e41 100644 --- a/todo/k_bild/k_bild.test.ts +++ b/todo/k_bild/k_bild.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -138,32 +138,32 @@ describe('k_bild', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => kbild_calculation({ K_BILD_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => kbild_calculation({ K_BILD_Q01: 8, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => kbild_calculation({ K_BILD_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/korq/korq.test.ts b/todo/korq/korq.test.ts index e7f9edd..d1f2496 100644 --- a/todo/korq/korq.test.ts +++ b/todo/korq/korq.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -135,32 +135,32 @@ describe('KORQ', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => korq_calculation({ Q01_KORQ: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => korq_calculation({ Q01_KORQ: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => korq_calculation({ Q01_KORQ: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/math/divide/divide.test.ts b/todo/math/divide/divide.test.ts index 210bf47..8387d92 100644 --- a/todo/math/divide/divide.test.ts +++ b/todo/math/divide/divide.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -47,12 +47,12 @@ describe('math_divide', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => divide_calculation({ DIVIDEND: 'a string', }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/math/multiply/multiply.test.ts b/todo/math/multiply/multiply.test.ts index de0a9b4..1a86e03 100644 --- a/todo/math/multiply/multiply.test.ts +++ b/todo/math/multiply/multiply.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -80,12 +80,12 @@ describe('math_multiply', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => multiply_calculation({ FACTOR_1: 'a string', }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/math/subtract/subtract.test.ts b/todo/math/subtract/subtract.test.ts index 55e00b9..b073586 100644 --- a/todo/math/subtract/subtract.test.ts +++ b/todo/math/subtract/subtract.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -47,12 +47,12 @@ describe('math_subtract', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => subtract_calculation({ MINUEND: 'a string', }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/math/sum/sum.test.ts b/todo/math/sum/sum.test.ts index 4aa2c3d..10c0bd9 100644 --- a/todo/math/sum/sum.test.ts +++ b/todo/math/sum/sum.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -80,12 +80,12 @@ describe('math_sum', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => sum_calculation({ ADDEND_1: 'a string', }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/mds_updrs/mds_updrs.test.ts b/todo/mds_updrs/mds_updrs.test.ts index 2e2e04d..4993e2b 100644 --- a/todo/mds_updrs/mds_updrs.test.ts +++ b/todo/mds_updrs/mds_updrs.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -447,7 +447,7 @@ describe('mds_updrs', function () { mds_updrs_calculation({ PART_1_Q1_COGNITIVE_IMPAIRMENT: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -456,7 +456,7 @@ describe('mds_updrs', function () { mds_updrs_calculation({ PART_1_Q1_COGNITIVE_IMPAIRMENT: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -465,7 +465,7 @@ describe('mds_updrs', function () { mds_updrs_calculation({ PART_1_Q1_COGNITIVE_IMPAIRMENT: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/mfis/mfis.test.ts b/todo/mfis/mfis.test.ts index 740eb67..7ec0418 100644 --- a/todo/mfis/mfis.test.ts +++ b/todo/mfis/mfis.test.ts @@ -126,32 +126,32 @@ describe('mfis', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mfis_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mfis_calculation({ Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mfis_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/mini_best_test/mini_best_test.test.ts b/todo/mini_best_test/mini_best_test.test.ts index 55cef9a..f4a2a5d 100644 --- a/todo/mini_best_test/mini_best_test.test.ts +++ b/todo/mini_best_test/mini_best_test.test.ts @@ -334,30 +334,30 @@ describe('mini_best_test', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mini_best_test_calculation({ MINI_BEST_TEST_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mini_best_test_calculation({ MINI_BEST_TEST_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mini_best_test_calculation({ MINI_BEST_TEST_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/mlks/mlks.test.ts b/todo/mlks/mlks.test.ts index 8bc9067..05e74f8 100644 --- a/todo/mlks/mlks.test.ts +++ b/todo/mlks/mlks.test.ts @@ -66,42 +66,42 @@ describe('MLKS', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mlks_calculation({ Q01_LIMP: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mlks_calculation({ Q01_LIMP: 30, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range for Q01_LIMP', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mlks_calculation({ Q04_GIVING_WAY_SENSATION_KNEE: 7, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mlks_calculation({ Q01_LIMP: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/mmse/mmse.test.ts b/todo/mmse/mmse.test.ts index 9ac2aca..eb6ed4a 100644 --- a/todo/mmse/mmse.test.ts +++ b/todo/mmse/mmse.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -132,65 +132,65 @@ describe('mmse', function () { mmse_calculation({ ORIENTATION_TO_TIME: "I'm not a number, you can't do math with me", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when called with a response where there are answers that are not allowed', function () { - it('should throw an InvalidInputsError when value on "ORIENTATION_TO_TIME" is out of the expected [0, 5] range', function () { + it('should throw an ZodError when value on "ORIENTATION_TO_TIME" is out of the expected [0, 5] range', function () { expect(() => mmse_calculation({ ORIENTATION_TO_TIME: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when value on "ORIENTATION_TO_PLACE" is out of the expected [0, 5] range', function () { + it('should throw an ZodError when value on "ORIENTATION_TO_PLACE" is out of the expected [0, 5] range', function () { expect(() => mmse_calculation({ ORIENTATION_TO_PLACE: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when value on "REGISTRATION" is out of the expected [0, 3] range', function () { + it('should throw an ZodError when value on "REGISTRATION" is out of the expected [0, 3] range', function () { expect(() => mmse_calculation({ REGISTRATION: 4, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when value on "ATTENTION_AND_CALCULATION" is out of the expected [0, 5] range', function () { + it('should throw an ZodError when value on "ATTENTION_AND_CALCULATION" is out of the expected [0, 5] range', function () { expect(() => mmse_calculation({ ATTENTION_AND_CALCULATION: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when value on "RECALL" is out of the expected [0, 3] range', function () { + it('should throw an ZodError when value on "RECALL" is out of the expected [0, 3] range', function () { expect(() => mmse_calculation({ RECALL: 4, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when value on "LANGUAGE" is out of the expected [0, 8] range', function () { + it('should throw an ZodError when value on "LANGUAGE" is out of the expected [0, 8] range', function () { expect(() => mmse_calculation({ LANGUAGE: 9, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('should throw an InvalidInputsError when value on "CONSTRUCT" is out of the expected [0, 1] range', function () { + it('should throw an ZodError when value on "CONSTRUCT" is out of the expected [0, 1] range', function () { expect(() => mmse_calculation({ CONSTRUCT: 2, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/moca/moca.test.ts b/todo/moca/moca.test.ts index 2ac970e..91895b2 100644 --- a/todo/moca/moca.test.ts +++ b/todo/moca/moca.test.ts @@ -333,7 +333,7 @@ describe('moca', function () { moca_calculation({ VISUOCONSTRUCTIONAL_SKILLS_CLOCK: [], }), - ).to.not.throw(InvalidInputsError) + ).to.not.throw(ZodError) }) }) @@ -343,7 +343,7 @@ describe('moca', function () { moca_calculation({ VISUOCONSTRUCTIONAL_SKILLS_CLOCK: ["I'm unexpected"], }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) @@ -355,7 +355,7 @@ describe('moca', function () { moca_calculation({ ALTERNATING_TRAIL_MARKING: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -364,7 +364,7 @@ describe('moca', function () { moca_calculation({ ALTERNATING_TRAIL_MARKING: 2, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/modified_caregiver_strain_index/modified_caregiver_strain_index.test.ts b/todo/modified_caregiver_strain_index/modified_caregiver_strain_index.test.ts index c7b4ade..71c8a96 100644 --- a/todo/modified_caregiver_strain_index/modified_caregiver_strain_index.test.ts +++ b/todo/modified_caregiver_strain_index/modified_caregiver_strain_index.test.ts @@ -150,7 +150,7 @@ describe('modified_caregiver_strain_index', function () { modified_caregiver_strain_index_calculation({ CSI_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) @@ -160,7 +160,7 @@ describe('modified_caregiver_strain_index', function () { modified_caregiver_strain_index_calculation({ CSI_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) @@ -170,7 +170,7 @@ describe('modified_caregiver_strain_index', function () { modified_caregiver_strain_index_calculation({ CSI_Q01: 3, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/mpi/mpi.test.ts b/todo/mpi/mpi.test.ts index d1818ac..1e1a366 100644 --- a/todo/mpi/mpi.test.ts +++ b/todo/mpi/mpi.test.ts @@ -353,30 +353,30 @@ describe('mpi', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mpi_calculation({ MPI_PART1_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mpi_calculation({ MPI_PART1_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => mpi_calculation({ MPI_PART1_Q01: 7, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/msq/msq.test.ts b/todo/msq/msq.test.ts index 42b7fef..7d53e31 100644 --- a/todo/msq/msq.test.ts +++ b/todo/msq/msq.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -348,32 +348,32 @@ describe('msq', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => msq_calculation({ DIGESTIVE_TRACT_Q01_NAUSEA_VOMITING: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => msq_calculation({ DIGESTIVE_TRACT_Q01_NAUSEA_VOMITING: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => msq_calculation({ DIGESTIVE_TRACT_Q01_NAUSEA_VOMITING: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/ndi/ndi.test.ts b/todo/ndi/ndi.test.ts index 88b51d1..3dc899b 100644 --- a/todo/ndi/ndi.test.ts +++ b/todo/ndi/ndi.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -129,30 +129,30 @@ describe('ndi calculation', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ndi_calculation({ NDI_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ndi_calculation({ NDI_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ndi_calculation({ NDI_Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/oas/oas.test.ts b/todo/oas/oas.test.ts index 8e99172..e482a23 100644 --- a/todo/oas/oas.test.ts +++ b/todo/oas/oas.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -222,12 +222,12 @@ describe('oas', function () { }) describe('when an answer is not not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oas_calculation({ OAS_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/orebro/long_version/ompq.test.ts b/todo/orebro/long_version/ompq.test.ts index 2fbf0a3..6529158 100644 --- a/todo/orebro/long_version/ompq.test.ts +++ b/todo/orebro/long_version/ompq.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -83,48 +83,48 @@ describe('ompq', function () { describe('validation', function () { describe('when question 5 is not passed as an array', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_calculation({ OMPQ_Q05: 'neck', }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when question 6 has an invalid minimum score', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_calculation({ OMPQ_Q06: 0, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when question 7 has an invalid minimum score', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_calculation({ OMPQ_Q07: 0, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when any other input has an invalid minimum score', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_calculation({ OMPQ_Q10: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when any other input has an invalid maximum score', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_calculation({ OMPQ_Q10: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/orebro/short_version/ompq_10.test.ts b/todo/orebro/short_version/ompq_10.test.ts index aa7aa98..85ad7a1 100644 --- a/todo/orebro/short_version/ompq_10.test.ts +++ b/todo/orebro/short_version/ompq_10.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -127,30 +127,30 @@ describe('ompq_10', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_10_calculation({ OREBRO_01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_10_calculation({ OREBRO_01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => ompq_10_calculation({ OREBRO_01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/oswestry/oswestry.test.ts b/todo/oswestry/oswestry.test.ts index 368133b..035637a 100644 --- a/todo/oswestry/oswestry.test.ts +++ b/todo/oswestry/oswestry.test.ts @@ -141,30 +141,30 @@ describe('oswestry', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oswestry_calculation({ '1_pain': "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oswestry_calculation({ '1_pain': -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oswestry_calculation({ '1_pain': 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/oxford_hip_score/oxford_hip_score.test.ts b/todo/oxford_hip_score/oxford_hip_score.test.ts index cc36b09..f9db47f 100644 --- a/todo/oxford_hip_score/oxford_hip_score.test.ts +++ b/todo/oxford_hip_score/oxford_hip_score.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -119,30 +119,30 @@ describe('oxford_hip_score', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oxford_hip_score_calculation({ ohs_01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oxford_hip_score_calculation({ ohs_01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oxford_hip_score_calculation({ ohs_01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/oxford_knee_score/oxford_knee_score.test.ts b/todo/oxford_knee_score/oxford_knee_score.test.ts index 72cef05..9283066 100644 --- a/todo/oxford_knee_score/oxford_knee_score.test.ts +++ b/todo/oxford_knee_score/oxford_knee_score.test.ts @@ -132,30 +132,30 @@ describe('oxford_knee_score', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oxford_knee_score_calculation({ '1_usual_knee_pain': "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oxford_knee_score_calculation({ '1_usual_knee_pain': -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => oxford_knee_score_calculation({ '1_usual_knee_pain': 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/paq_c/paq_c.test.ts b/todo/paq_c/paq_c.test.ts index 8aa5131..8b756c7 100644 --- a/todo/paq_c/paq_c.test.ts +++ b/todo/paq_c/paq_c.test.ts @@ -241,7 +241,7 @@ describe('paq_c', function () { paq_c_calculation({ ITEM_1_ACTIVITY_01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -250,7 +250,7 @@ describe('paq_c', function () { paq_c_calculation({ ITEM_1_ACTIVITY_01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -259,7 +259,7 @@ describe('paq_c', function () { paq_c_calculation({ ITEM_1_ACTIVITY_01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/pci/pci.test.ts b/todo/pci/pci.test.ts index 92c656c..15e7a31 100644 --- a/todo/pci/pci.test.ts +++ b/todo/pci/pci.test.ts @@ -539,30 +539,30 @@ describe('pci', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pci_calculation({ PCI_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pci_calculation({ PCI_Q01: 0, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pci_calculation({ PCI_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/pcl_5/pcl_5.test.ts b/todo/pcl_5/pcl_5.test.ts index 7130342..5ff7207 100644 --- a/todo/pcl_5/pcl_5.test.ts +++ b/todo/pcl_5/pcl_5.test.ts @@ -149,32 +149,32 @@ describe('pcl_5', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pcl_5_calculation({ PCL5_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pcl_5_calculation({ PCL5_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pcl_5_calculation({ PCL5_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/pcs/pcs.test.ts b/todo/pcs/pcs.test.ts index 89ca6f9..bddf6cf 100644 --- a/todo/pcs/pcs.test.ts +++ b/todo/pcs/pcs.test.ts @@ -249,30 +249,30 @@ describe('pcs', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pcs_calculation({ question_1: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pcs_calculation({ question_1: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected [0,4] range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pcs_calculation({ question_1: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/pdi/pdi.test.ts b/todo/pdi/pdi.test.ts index e9e5888..86367c3 100644 --- a/todo/pdi/pdi.test.ts +++ b/todo/pdi/pdi.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -58,32 +58,32 @@ describe('pdi', function () { }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pdi_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pdi_calculation({ Q01: 12, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when there are non-numerical answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pdi_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/physical_activity_measurements/physical_activity_measurements.test.ts b/todo/physical_activity_measurements/physical_activity_measurements.test.ts index 71d8478..e6c7d4c 100644 --- a/todo/physical_activity_measurements/physical_activity_measurements.test.ts +++ b/todo/physical_activity_measurements/physical_activity_measurements.test.ts @@ -161,30 +161,30 @@ describe('physical_activity_measurement', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => physical_activity_measurement_calculation({ LIGHT_PA_DAYS_PER_WEEK: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not one of the allowed answers (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => physical_activity_measurement_calculation({ LIGHT_PA_DAYS_PER_WEEK: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed one of the allowed answers (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => physical_activity_measurement_calculation({ LIGHT_PA_DAYS_PER_WEEK: 8, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/posas_observer/posas_observer.test.ts b/todo/posas_observer/posas_observer.test.ts index 0947394..1f6b86e 100644 --- a/todo/posas_observer/posas_observer.test.ts +++ b/todo/posas_observer/posas_observer.test.ts @@ -122,30 +122,30 @@ describe('posas_observer', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => posas_obsever_calculation({ VASCULARISATION: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => posas_obsever_calculation({ VASCULARISATION: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => posas_obsever_calculation({ VASCULARISATION: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/posas_patient/posas_patient.test.ts b/todo/posas_patient/posas_patient.test.ts index fa341b1..a35a186 100644 --- a/todo/posas_patient/posas_patient.test.ts +++ b/todo/posas_patient/posas_patient.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -122,30 +122,30 @@ describe('posas_patient', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => posas_patient_calculation({ PAIN: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => posas_patient_calculation({ PAIN: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => posas_patient_calculation({ PAIN: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/pro_ctcae/pro_ctcae.test.ts b/todo/pro_ctcae/pro_ctcae.test.ts index f16eabb..551b6e8 100644 --- a/todo/pro_ctcae/pro_ctcae.test.ts +++ b/todo/pro_ctcae/pro_ctcae.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -200,30 +200,30 @@ describe('pro_ctcae', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pro_ctcae_calculation({ proctcae_1_dry_mouth_severity: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pro_ctcae_calculation({ proctcae_1_dry_mouth_severity: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => pro_ctcae_calculation({ proctcae_1_dry_mouth_severity: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/promis_10/promis_10.test.ts b/todo/promis_10/promis_10.test.ts index 2e2e331..bdb46c2 100644 --- a/todo/promis_10/promis_10.test.ts +++ b/todo/promis_10/promis_10.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -254,30 +254,30 @@ describe('promis_10', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => promis_10_calculation({ PROMIS_10_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => promis_10_calculation({ PROMIS_10_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the expected range', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => promis_10_calculation({ PROMIS_10_Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/prtee/prtee.test.ts b/todo/prtee/prtee.test.ts index b25a945..8847d2f 100644 --- a/todo/prtee/prtee.test.ts +++ b/todo/prtee/prtee.test.ts @@ -258,30 +258,30 @@ describe('prtee', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => prtee_calculation({ PAIN_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => prtee_calculation({ PAIN_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => prtee_calculation({ PAIN_Q01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/psk/psk.test.ts b/todo/psk/psk.test.ts index 966211d..0f69bba 100644 --- a/todo/psk/psk.test.ts +++ b/todo/psk/psk.test.ts @@ -147,30 +147,30 @@ describe('psk', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => psk_calculation({ SCORE_FOR_ACTIVITY_01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => psk_calculation({ SCORE_FOR_ACTIVITY_01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => psk_calculation({ SCORE_FOR_ACTIVITY_01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/psqi/psqi.test.ts b/todo/psqi/psqi.test.ts index 962d6ce..0f197e2 100644 --- a/todo/psqi/psqi.test.ts +++ b/todo/psqi/psqi.test.ts @@ -141,52 +141,52 @@ describe('psqi', function () { }) describe('Input validations', function () { - it('when an answer is below the expected range for question with hours: should throw an InvalidInputsError', function () { + it('when an answer is below the expected range for question with hours: should throw an ZodError', function () { expect(() => psqi_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('when an answer is above the expected range for question with hours: should throw an InvalidInputsError', function () { + it('when an answer is above the expected range for question with hours: should throw an ZodError', function () { expect(() => psqi_calculation({ Q01: 25, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('when there are non-numerical answers: should throw an InvalidInputsError', function () { + it('when there are non-numerical answers: should throw an ZodError', function () { expect(() => psqi_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('when an answer is below the expected range for question with standard input: should throw an InvalidInputsError', function () { + it('when an answer is below the expected range for question with standard input: should throw an ZodError', function () { expect(() => psqi_calculation({ Q06: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('when an answer is above the expected range for question with standard input: should throw an InvalidInputsError', function () { + it('when an answer is above the expected range for question with standard input: should throw an ZodError', function () { expect(() => psqi_calculation({ Q06: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) - it('when there are non-numerical answers with standard input: should throw an InvalidInputsError', function () { + it('when there are non-numerical answers with standard input: should throw an ZodError', function () { expect(() => psqi_calculation({ Q06: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) diff --git a/todo/qol_stoma/qol_stoma.test.ts b/todo/qol_stoma/qol_stoma.test.ts index db44abe..045181e 100644 --- a/todo/qol_stoma/qol_stoma.test.ts +++ b/todo/qol_stoma/qol_stoma.test.ts @@ -136,30 +136,30 @@ describe('qol_stoma', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => qol_stoma_calculation({ QOL_STOMA_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => qol_stoma_calculation({ QOL_STOMA_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => qol_stoma_calculation({ QOL_STOMA_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/quickdash/quickdash.test.ts b/todo/quickdash/quickdash.test.ts index e8e8272..c8d345a 100644 --- a/todo/quickdash/quickdash.test.ts +++ b/todo/quickdash/quickdash.test.ts @@ -330,30 +330,30 @@ describe('quickdash', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => quickdash_calculation({ QUICKDASH_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => quickdash_calculation({ QUICKDASH_Q01: 0, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => quickdash_calculation({ QUICKDASH_Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/scl90/scl90.test.ts b/todo/scl90/scl90.test.ts index df2eefa..ed5e00d 100644 --- a/todo/scl90/scl90.test.ts +++ b/todo/scl90/scl90.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } from '../../errors' import { inputsInSubscaleLens } from '../../lib/calculation_variants/api/subscale/lenses' import { execute_test_calculation } from '../../lib/execute_test_calculation' import { get_result_ids_from_calculation_output } from '../../lib/get_result_ids_from_calculation_output' @@ -527,7 +527,7 @@ describe('scl90', function () { scl90_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -536,7 +536,7 @@ describe('scl90', function () { scl90_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -545,7 +545,7 @@ describe('scl90', function () { scl90_calculation({ Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/scl90r/scl90r.test.ts b/todo/scl90r/scl90r.test.ts index d3866a9..2190958 100644 --- a/todo/scl90r/scl90r.test.ts +++ b/todo/scl90r/scl90r.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } from '../../errors' import { inputsInSubscaleLens, subscaleIdLens, @@ -547,21 +547,21 @@ describe('scl90r', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => scl90r_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => scl90r_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -570,7 +570,7 @@ describe('scl90r', function () { scl90r_calculation({ Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/sdq/sdq.test.ts b/todo/sdq/sdq.test.ts index f8944ec..250b4a8 100644 --- a/todo/sdq/sdq.test.ts +++ b/todo/sdq/sdq.test.ts @@ -629,7 +629,7 @@ describe('sdq', function () { sdq_calculation({ EMOTIONAL_PROBLEMS_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { @@ -638,7 +638,7 @@ describe('sdq', function () { sdq_calculation({ EMOTIONAL_PROBLEMS_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { @@ -647,7 +647,7 @@ describe('sdq', function () { sdq_calculation({ EMOTIONAL_PROBLEMS_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/sf36/sf36.test.ts b/todo/sf36/sf36.test.ts index 218f949..7d3e421 100644 --- a/todo/sf36/sf36.test.ts +++ b/todo/sf36/sf36.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -400,30 +400,30 @@ describe('sf36', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => sf36_calculation({ SF36_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => sf36_calculation({ SF36_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => sf36_calculation({ SF36_Q01: 6, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/spadi/spadi.test.ts b/todo/spadi/spadi.test.ts index c9a46e2..afed314 100644 --- a/todo/spadi/spadi.test.ts +++ b/todo/spadi/spadi.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -205,30 +205,30 @@ describe('spadi', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => spadi_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is below the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => spadi_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not allowed (e.g. is above the expected range)', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => spadi_calculation({ Q01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/start_back_screening_tool/start_back_screening_tool.test.ts b/todo/start_back_screening_tool/start_back_screening_tool.test.ts index 5648a22..236f4f1 100644 --- a/todo/start_back_screening_tool/start_back_screening_tool.test.ts +++ b/todo/start_back_screening_tool/start_back_screening_tool.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -196,30 +196,30 @@ describe('start_back_screening_tool', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => start_back_calculation({ Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => start_back_calculation({ Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => start_back_calculation({ Q01: 2, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/visa/visa_a/visa_a.test.ts b/todo/visa/visa_a/visa_a.test.ts index 6e856e7..beead2b 100644 --- a/todo/visa/visa_a/visa_a.test.ts +++ b/todo/visa/visa_a/visa_a.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import { compose } from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -127,21 +127,21 @@ describe('visa_a', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => visa_a_calculation({ VISA_A_Q1: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => visa_a_calculation({ VISA_A_Q1: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/visa/visa_g/visa_g.test.ts b/todo/visa/visa_g/visa_g.test.ts index ca1f44c..ac993a1 100644 --- a/todo/visa/visa_g/visa_g.test.ts +++ b/todo/visa/visa_g/visa_g.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import { compose } from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -127,21 +127,21 @@ describe('visa_g', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => visa_g_calculation({ VISA_G_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => visa_g_calculation({ VISA_G_Q01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/visa/visa_p/visa_p.test.ts b/todo/visa/visa_p/visa_p.test.ts index 5aab19d..8c9bcda 100644 --- a/todo/visa/visa_p/visa_p.test.ts +++ b/todo/visa/visa_p/visa_p.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import { compose } from 'ramda' -import { InvalidInputsError } from '../../../errors' +import { ZodError } 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' @@ -127,21 +127,21 @@ describe('visa_p', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => visa_p_calculation({ VISA_P_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is not one of the allowed answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => visa_p_calculation({ VISA_P_Q01: 11, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/todo/zarit_12/zarit_12.test.ts b/todo/zarit_12/zarit_12.test.ts index 9772b23..12e98cd 100644 --- a/todo/zarit_12/zarit_12.test.ts +++ b/todo/zarit_12/zarit_12.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import R from 'ramda' -import { InvalidInputsError } from '../../errors' +import { ZodError } 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' @@ -128,30 +128,30 @@ describe('zarit_12', function () { describe('values entered by the user are checked to verify they are inside specified ranges', function () { describe('when an answer is not a number', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => zarit_12_calculation({ ZARIT_12_Q01: "I'm not a number", }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is below one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => zarit_12_calculation({ ZARIT_12_Q01: -1, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) describe('when an answer is above one of the expected answers', function () { - it('should throw an InvalidInputsError', function () { + it('should throw an ZodError', function () { expect(() => zarit_12_calculation({ ZARIT_12_Q01: 5, }), - ).toThrow(InvalidInputsError) + ).toThrow(ZodError) }) }) }) diff --git a/yarn.lock b/yarn.lock index 94aff81..cb2b8f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,9 +30,8 @@ __metadata: dependencies: "@types/cpx": "npm:^1" "@types/jest": "npm:^29.5.14" - "@types/lodash": "npm:^4.14.186" + "@types/lodash": "npm:^4" "@types/node": "npm:^18.7.23" - "@types/ramda": "npm:^0.28.15" "@types/showdown": "npm:^2.0.0" "@typescript-eslint/eslint-plugin": "npm:^8.18.2" "@typescript-eslint/parser": "npm:^8.18.2" @@ -42,11 +41,9 @@ __metadata: husky: "npm:^9.1.7" jest: "npm:^29.7.0" lodash: "npm:^4.17.21" - mathjs: "npm:^14.0.1" - moment: "npm:^2.30.1" + mockdate: "npm:^3.0.5" pre-commit: "npm:^1.2.2" prettier: "npm:^3.4.2" - ramda: "npm:^0.30.1" showdown: "npm:^2.1.0" ts-jest: "npm:^29.2.5" typescript: "npm:^5.7.2" @@ -380,15 +377,6 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.25.7": - version: 7.26.0 - resolution: "@babel/runtime@npm:7.26.0" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10/9f4ea1c1d566c497c052d505587554e782e021e6ccd302c2ad7ae8291c8e16e3f19d4a7726fb64469e057779ea2081c28b7dbefec6d813a22f08a35712c0f699 - languageName: node - linkType: hard - "@babel/template@npm:^7.25.9, @babel/template@npm:^7.3.3": version: 7.25.9 resolution: "@babel/template@npm:7.25.9" @@ -1103,37 +1091,28 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.186": - version: 4.17.13 - resolution: "@types/lodash@npm:4.17.13" - checksum: 10/ddb34e20810c71be2d9445bcc4b64ec25b83976738454de709854b79c7f655b03704b76235445699956d65012987720e0e429a35489de65495cdb5420202d905 +"@types/lodash@npm:^4": + version: 4.17.14 + resolution: "@types/lodash@npm:4.17.14" + checksum: 10/6ee40725f3e192f5ef1f493caca19210aa7acd7adc3136b8dba84d418a35be0abea0668105aed9f696ad62a54310a9c0d328971ad4b157f5bcda700424ed5aae languageName: node linkType: hard "@types/node@npm:*": - version: 22.10.2 - resolution: "@types/node@npm:22.10.2" + version: 22.10.5 + resolution: "@types/node@npm:22.10.5" dependencies: undici-types: "npm:~6.20.0" - checksum: 10/451adfefed4add58b069407173e616220fd4aaa3307cdde1bb701aa053b65b54ced8483db2f870dcedec7a58cb3b06101fbc19d85852716672ec1fd3660947fa + checksum: 10/a5366961ffa9921e8f15435bc18ea9f8b7a7bb6b3d92dd5e93ebcd25e8af65708872bd8e6fee274b4655bab9ca80fbff9f0e42b5b53857790f13cf68cf4cbbfc languageName: node linkType: hard "@types/node@npm:^18.7.23": - version: 18.19.68 - resolution: "@types/node@npm:18.19.68" + version: 18.19.69 + resolution: "@types/node@npm:18.19.69" dependencies: undici-types: "npm:~5.26.4" - checksum: 10/024a4a8eeca21c0d1eaa575036dbc44528eae180821de71b77868ddc24d18032b988582046db4f7ea2643970a5169d790e1884153472145de07d629bc2ce2ec6 - languageName: node - linkType: hard - -"@types/ramda@npm:^0.28.15": - version: 0.28.25 - resolution: "@types/ramda@npm:0.28.25" - dependencies: - ts-toolbelt: "npm:^6.15.1" - checksum: 10/507400af2bdb855850dda32ede0eb294077ed4c3f1c4af160541efc6e0579e0f425ff56e121fbdf886696286495d7d422068d0e804d88a4550a3edf324ca4b27 + checksum: 10/fe34976dd1b5ecb2183f196bcbd7dd22fc165268530425edb936f2fd593baaaf19bb93f1955104364ee9bcb2d368359b9df604382de4d8e6dc273e887dc90531 languageName: node linkType: hard @@ -2098,13 +2077,6 @@ __metadata: languageName: node linkType: hard -"complex.js@npm:^2.2.5": - version: 2.4.2 - resolution: "complex.js@npm:2.4.2" - checksum: 10/089257e0f09b3c9f52b4f7e009abb762a924d820fe01002da61bf9a3cee28c364a77de4d26ba8623c4fac017feb6856797da0713f8c165f795914be0c9e0b127 - languageName: node - linkType: hard - "component-emitter@npm:^1.2.1": version: 1.3.1 resolution: "component-emitter@npm:1.3.1" @@ -2240,13 +2212,6 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.4.3": - version: 10.4.3 - resolution: "decimal.js@npm:10.4.3" - checksum: 10/de663a7bc4d368e3877db95fcd5c87b965569b58d16cdc4258c063d231ca7118748738df17cd638f7e9dd0be8e34cec08d7234b20f1f2a756a52fc5a38b188d0 - languageName: node - linkType: hard - "decode-uri-component@npm:^0.2.0": version: 0.2.2 resolution: "decode-uri-component@npm:0.2.2" @@ -2453,13 +2418,6 @@ __metadata: languageName: node linkType: hard -"escape-latex@npm:^1.2.0": - version: 1.2.0 - resolution: "escape-latex@npm:1.2.0" - checksum: 10/73a787319f0965ecb8244bb38bf3a3cba872f0b9a5d3da8821140e9f39fe977045dc953a62b1a2bed4d12bfccbe75a7d8ec786412bf00739eaa2f627d0a8e0d6 - languageName: node - linkType: hard - "escape-string-regexp@npm:^2.0.0": version: 2.0.0 resolution: "escape-string-regexp@npm:2.0.0" @@ -2909,13 +2867,6 @@ __metadata: languageName: node linkType: hard -"fraction.js@npm:^5.2.1": - version: 5.2.1 - resolution: "fraction.js@npm:5.2.1" - checksum: 10/ea6789794274817610b6b8ae5713d1e81a04903e19b1c6d57c958fb15abb4ea7187a630011ceae5f474ed9871268bbc80abbbbfa3cc7d66bc9c5e60835aa1f27 - languageName: node - linkType: hard - "fragment-cache@npm:^0.2.1": version: 0.2.1 resolution: "fragment-cache@npm:0.2.1" @@ -3711,13 +3662,6 @@ __metadata: languageName: node linkType: hard -"javascript-natural-sort@npm:^0.7.1": - version: 0.7.1 - resolution: "javascript-natural-sort@npm:0.7.1" - checksum: 10/7bf6eab67871865d347f09a95aa770f9206c1ab0226bcda6fdd9edec340bf41111a7f82abac30556aa16a21cfa3b2b1ca4a362c8b73dd5ce15220e5d31f49d79 - languageName: node - linkType: hard - "jest-changed-files@npm:^29.7.0": version: 29.7.0 resolution: "jest-changed-files@npm:29.7.0" @@ -4444,25 +4388,6 @@ __metadata: languageName: node linkType: hard -"mathjs@npm:^14.0.1": - version: 14.0.1 - resolution: "mathjs@npm:14.0.1" - dependencies: - "@babel/runtime": "npm:^7.25.7" - complex.js: "npm:^2.2.5" - decimal.js: "npm:^10.4.3" - escape-latex: "npm:^1.2.0" - fraction.js: "npm:^5.2.1" - javascript-natural-sort: "npm:^0.7.1" - seedrandom: "npm:^3.0.5" - tiny-emitter: "npm:^2.1.0" - typed-function: "npm:^4.2.1" - bin: - mathjs: bin/cli.js - checksum: 10/a3eed2f2b8834b5232678efc9ebc158ecd16fb6ff1c63cf4d6dc62768f66cd9ad73199dda19c4fde5af71fe66085fd32fa50f323d568de6d77167e7114e6a3e6 - languageName: node - linkType: hard - "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -4717,10 +4642,10 @@ __metadata: languageName: node linkType: hard -"moment@npm:^2.30.1": - version: 2.30.1 - resolution: "moment@npm:2.30.1" - checksum: 10/ae42d876d4ec831ef66110bdc302c0657c664991e45cf2afffc4b0f6cd6d251dde11375c982a5c0564ccc0fa593fc564576ddceb8c8845e87c15f58aa6baca69 +"mockdate@npm:^3.0.5": + version: 3.0.5 + resolution: "mockdate@npm:3.0.5" + checksum: 10/ff74f43f56a12e1339e838aee623e37b6e4c378173905697f2a006a5c581eea9c71da54fcea76c27e7e744422e49395c668932bf09e67f024841240ffef91fd2 languageName: node linkType: hard @@ -5238,13 +5163,6 @@ __metadata: languageName: node linkType: hard -"ramda@npm:^0.30.1": - version: 0.30.1 - resolution: "ramda@npm:0.30.1" - checksum: 10/f3e1a7bc11f3a113edb3bb4764c2c22088c5896594934c01cf1980184d00f1d5a7af82761a3389419e2d51542ad2121ff44e718f40792d167e2846bba79a4c6d - languageName: node - linkType: hard - "randomatic@npm:^3.0.0": version: 3.1.1 resolution: "randomatic@npm:3.1.1" @@ -5296,13 +5214,6 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.14.0": - version: 0.14.1 - resolution: "regenerator-runtime@npm:0.14.1" - checksum: 10/5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471 - languageName: node - linkType: hard - "regex-cache@npm:^0.4.2": version: 0.4.4 resolution: "regex-cache@npm:0.4.4" @@ -5500,13 +5411,6 @@ __metadata: languageName: node linkType: hard -"seedrandom@npm:^3.0.5": - version: 3.0.5 - resolution: "seedrandom@npm:3.0.5" - checksum: 10/acad5e516c04289f61c2fb9848f449b95f58362b75406b79ec51e101ec885293fc57e3675d2f39f49716336559d7190f7273415d185fead8cd27b171ebf7d8fb - languageName: node - linkType: hard - "semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -5937,13 +5841,6 @@ __metadata: languageName: node linkType: hard -"tiny-emitter@npm:^2.1.0": - version: 2.1.0 - resolution: "tiny-emitter@npm:2.1.0" - checksum: 10/75633f4de4f47f43af56aff6162f25b87be7efc6f669fda256658f3c3f4a216f23dc0d13200c6fafaaf1b0c7142f0201352fb06aec0b77f68aea96be898f4516 - languageName: node - linkType: hard - "tinylogic@npm:^2.0.0": version: 2.0.0 resolution: "tinylogic@npm:2.0.0" @@ -6051,13 +5948,6 @@ __metadata: languageName: node linkType: hard -"ts-toolbelt@npm:^6.15.1": - version: 6.15.5 - resolution: "ts-toolbelt@npm:6.15.5" - checksum: 10/1816b11f6a4ca7b11da1e81613dda217535718862c9c7c1d9e5dbeb12abc765b6803dbc0c90ee8a5c1b782bc369e2851913005042921028d16e6ae8bf054b2da - languageName: node - linkType: hard - "tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -6102,13 +5992,6 @@ __metadata: languageName: node linkType: hard -"typed-function@npm:^4.2.1": - version: 4.2.1 - resolution: "typed-function@npm:4.2.1" - checksum: 10/2218d6e4a56c414c2d9c1e3cf2f0d26d6a8848d3e875cbd0eec5a791c25c4ee182cb488a6077b45b110334de7bd7f44fb049feac9e5216bef3172c22acbbf501 - languageName: node - linkType: hard - "typedarray@npm:^0.0.6": version: 0.0.6 resolution: "typedarray@npm:0.0.6"