From 71e1c86ad2bb58dfd6964ccb20699dce03d6778c Mon Sep 17 00:00:00 2001 From: Devon Colmer <935806+d3vco@users.noreply.github.com> Date: Sun, 8 Dec 2024 09:29:47 -0500 Subject: [PATCH] feat: allow incomplete fact selection --- package.json | 1 + .../operations/AddPotentialLinkModal.vue | 16 +------- src/tests/utils.test.js | 37 +++++++++++++++++++ src/utils/utils.js | 18 +++++++++ 4 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 src/tests/utils.test.js diff --git a/package.json b/package.json index a731c2a..ae1233d 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "preview": "vite preview --port 5050", "lint": "npx eslint \"./**\"", "lintfix": "npx eslint \"./**\" --fix", + "test": "jest --config jest.config.js", "test-all": "jest --config jest.config.js && npx eslint \"./**\"", "test-accessibility": "jest -t=accessibility --config jest.config.js" }, diff --git a/src/components/operations/AddPotentialLinkModal.vue b/src/components/operations/AddPotentialLinkModal.vue index b37a02d..9a7e5a7 100644 --- a/src/components/operations/AddPotentialLinkModal.vue +++ b/src/components/operations/AddPotentialLinkModal.vue @@ -8,6 +8,7 @@ import { useOperationStore } from '@/stores/operationStore'; import { useAgentStore } from "@/stores/agentStore"; import { useAbilityStore } from "@/stores/abilityStore"; import { useSourceStore } from "@/stores/sourceStore"; +import { cartesian } from "@/utils/utils"; const props = defineProps({ active: Boolean, @@ -47,21 +48,8 @@ const filteredAbilities = computed(() => { const potentialLinksToAdd = computed(() => { let links = []; - function cartesian(args) { - if (!args.length) return []; - let r = [], max = args.length - 1; - function helper(arr, i) { - for (let j = 0; j < args[i].length; j++) { - let a = arr.slice(0); - a.push(args[i][j]); - (i === max) ? r.push(a) : helper(a, i + 1); - } - } - helper([], 0); - return r; - } - let combinations = []; + Object.keys(selectedPotentialLinkFacts.value).forEach((factName, i) => { combinations.push(selectedPotentialLinkFacts.value[factName].facts.filter((fact) => fact.selected).map((fact) => `${factName.length}|${factName}${fact.value}`)); if (selectedPotentialLinkFacts.value[factName].customValue) { diff --git a/src/tests/utils.test.js b/src/tests/utils.test.js new file mode 100644 index 0000000..09c3725 --- /dev/null +++ b/src/tests/utils.test.js @@ -0,0 +1,37 @@ +import { cartesian } from '../utils/utils'; + +describe('cartesian function', () => { + it('should return an empty array when input is empty', () => { + expect(cartesian([])).toEqual([]); + }); + + it('should return the correct cartesian product for non-empty arrays', () => { + const input = [[1, 2], [3, 4]]; + const expectedOutput = [ + [1, 3], + [1, 4], + [2, 3], + [2, 4] + ]; + expect(cartesian(input)).toEqual(expectedOutput); + }); + + it('should allow arrays with empty sub-arrays', () => { + const input = [[1, 2], [], [3, 4]]; + const expectedOutput = [ + [1, 3], + [1, 4], + [2, 3], + [2, 4] + ]; + expect(cartesian(input)).toEqual(expectedOutput); + }); + + it('should handle arrays with single elements', () => { + const input = [[1], [2], [3]]; + const expectedOutput = [ + [1, 2, 3] + ]; + expect(cartesian(input)).toEqual(expectedOutput); + }); +}); diff --git a/src/utils/utils.js b/src/utils/utils.js index e1a297b..bd82cd1 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -127,3 +127,21 @@ export function b64DecodeUnicode(str) { } } else return ""; } + +export function cartesian(args) { + // Remove empty arrays from the input + const filteredArgs = args.filter(arr => arr.length > 0); + if (!filteredArgs.length) return []; + let r = [], max = filteredArgs.length - 1; + + function helper(arr, i) { + for (const element of filteredArgs[i]) { + let a = arr.slice(0); + a.push(element); + (i === max) ? r.push(a) : helper(a, i + 1); + } + } + + helper([], 0); + return r; +} \ No newline at end of file