From 2b2092a4a4ea6cc85cb45ba206a090761a76811c Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 4 Nov 2023 18:04:32 +0100 Subject: [PATCH] Added sending feedback if alg found solution. --- src/alg/TimeDistribution.ts | 12 +- .../TimeDistribution/DistributeStudents.ts | 11 +- src/alg/TimeDistribution/FindPaths.ts | 8 +- test/failData.ts | 334 ++++++++++++++++++ test/timeDistribution.test.ts | 8 +- 5 files changed, 362 insertions(+), 11 deletions(-) create mode 100644 test/failData.ts diff --git a/src/alg/TimeDistribution.ts b/src/alg/TimeDistribution.ts index 139a813..556c91c 100644 --- a/src/alg/TimeDistribution.ts +++ b/src/alg/TimeDistribution.ts @@ -26,13 +26,15 @@ function main( students: Student[], project: Project, polls: PollQuestion[] -): Item[] { - let groups = buildGroupsByPaths(polls, students); +): boolean { + const groups = buildGroupsByPaths(polls, students); const g = createGraph(items); - groups = findPathsForTheGroups(groups, items, g, project); - distributeStudentsToPaths(items, groups); + const res = findPathsForTheGroups(groups, items, g, project); + if (!res) return false; + const res2 = distributeStudentsToPaths(items, groups); + if (!res2) return false; allocateGroupsToItems(items, groups, project); - return items; + return true; } export { main, getVotingIds }; diff --git a/src/alg/TimeDistribution/DistributeStudents.ts b/src/alg/TimeDistribution/DistributeStudents.ts index 1ce239e..7b7ba72 100644 --- a/src/alg/TimeDistribution/DistributeStudents.ts +++ b/src/alg/TimeDistribution/DistributeStudents.ts @@ -10,26 +10,33 @@ function distributeStudentsToPaths(items: Item[], groups: Group[]) { relevantItems, amountRelevantStudents(changableGroups) ); - distributeWithMinimumCapacity(changableGroups, relevantItems); + return distributeWithMinimumCapacity(changableGroups, relevantItems); } function distributeWithMinimumCapacity( changableGroups: Group[], relevantItems: Item[] ) { + let working = true; changableGroups.forEach((group) => { + let amountStudents = group.studentIds.length; group.paths.forEach((path) => { const minCapacity = Math.min( - ...path.path.map((pathItem) => pathItem.updatedGroupCapacity) + ...path.path.map((pathItem) => pathItem.updatedGroupCapacity), + group.studentIds.length ); path.valueForTestingStudentDistribution = minCapacity; + amountStudents -= minCapacity; relevantItems.forEach((item) => { if (path.path.includes(item)) { item.updatedGroupCapacity -= minCapacity; } }); }); + + if (amountStudents > 0) working = false; }); + return working; } function amountRelevantStudents(changableGroups: Group[]) { diff --git a/src/alg/TimeDistribution/FindPaths.ts b/src/alg/TimeDistribution/FindPaths.ts index 2385ede..9ad8c28 100644 --- a/src/alg/TimeDistribution/FindPaths.ts +++ b/src/alg/TimeDistribution/FindPaths.ts @@ -10,16 +10,18 @@ function findPathsForTheGroups( g: DirectedGraph, project: Project, requiredIds: Set = new Set(getDefaultIds(project)) -): Group[] { +): boolean { const entries = g.getNodesWithoutIngoingEdges(); groups.forEach((group) => { const ids = new Set([...requiredIds, ...group.requiredEvents]); entries.forEach((entry: GraphNode) => { dfs(entry, ids, [], group.requiredEvents, group, items); }); + if (group.paths.length == 0) { + return false; + } }); - - return groups; + return true; } function dfs( diff --git a/test/failData.ts b/test/failData.ts new file mode 100644 index 0000000..0254a4f --- /dev/null +++ b/test/failData.ts @@ -0,0 +1,334 @@ +import PollQuestion from '../src/types/Polls'; +import Student from '../src/types/Student'; +import Item from '../src/types/Item'; +import Project from '../src/types/Project'; + +const items: Item[] = [ + { + _id: 'id1', + title: 'Meeting 1', + startTime: new Date(2023, 8, 16, 9, 0), + endTime: new Date(2023, 8, 16, 10, 0), + eventId: 'group1', + studentIds: [], + groupCapazity: 100, + updatedGroupCapacity: 100, + }, + { + _id: 'id2', + title: 'Lunch Break', + startTime: new Date(2023, 8, 16, 9, 0), + endTime: new Date(2023, 8, 16, 10, 0), + eventId: 'group2', + studentIds: [], + groupCapazity: 50, + updatedGroupCapacity: 50, + }, + { + _id: 'id3', + title: 'Meeting 2', + startTime: new Date(2023, 8, 16, 14, 0), + endTime: new Date(2023, 8, 16, 15, 0), + eventId: 'group3', + studentIds: [], + groupCapazity: 50, + updatedGroupCapacity: 50, + }, + { + _id: 'id4', + title: 'Training Session', + startTime: new Date(2023, 8, 17, 10, 30), + endTime: new Date(2023, 8, 17, 12, 0), + eventId: 'solo3', + studentIds: [], + groupCapazity: 20, + updatedGroupCapacity: 20, + }, + { + _id: 'id5', + title: 'Project Discussion', + startTime: new Date(2023, 8, 17, 14, 0), + endTime: new Date(2023, 8, 17, 15, 30), + eventId: 'group2', + studentIds: [], + groupCapazity: 50, + updatedGroupCapacity: 50, + }, + { + _id: 'id6', + title: 'Client Meeting', + startTime: new Date(2023, 8, 18, 11, 0), + endTime: new Date(2023, 8, 18, 12, 0), + eventId: 'group1', + studentIds: [], + groupCapazity: 50, + updatedGroupCapacity: 50, + }, + { + _id: 'poll1', + title: 'poll', + startTime: new Date(2023, 8, 18, 11, 0), + endTime: new Date(2023, 8, 18, 12, 0), + eventId: 'poll1', + studentIds: [], + groupCapazity: 100, + updatedGroupCapacity: 100, + }, + { + _id: 'id7', + title: 'Coffee Break', + startTime: new Date(2023, 8, 18, 15, 30), + endTime: new Date(2023, 8, 18, 15, 45), + eventId: 'solo4', + studentIds: [], + groupCapazity: 100, + updatedGroupCapacity: 100, + }, + { + _id: 'id8', + title: 'Team Meeting', + startTime: new Date(2023, 8, 19, 9, 30), + endTime: new Date(2023, 8, 19, 10, 30), + eventId: 'solo5', + studentIds: [], + groupCapazity: 2, + updatedGroupCapacity: 2, + }, + + { + _id: 'id9', + title: 'Workshop', + startTime: new Date(2023, 8, 19, 13, 0), + endTime: new Date(2023, 8, 19, 15, 0), + eventId: 'solo2', + studentIds: [], + groupCapazity: 100, + updatedGroupCapacity: 100, + }, + { + _id: 'id10', + title: 'Project Review', + startTime: new Date(2023, 8, 20, 14, 0), + endTime: new Date(2023, 8, 20, 15, 30), + eventId: 'group3', + studentIds: [], + groupCapazity: 50, + updatedGroupCapacity: 50, + }, + { + _id: 'id11', + title: 'Project Review', + startTime: new Date(2023, 8, 21, 14, 0), + endTime: new Date(2023, 8, 21, 15, 30), + eventId: 'poll2', + studentIds: [], + groupCapazity: 100, + updatedGroupCapacity: 100, + }, +]; + +export { items }; + +const polls: PollQuestion[] = [ + { + _id: 'id0', + text: 'Wählt eine Veranstaltung!', + choices: [ + { + _id: 'id1', + eventId: 'poll2', + studentIds: [ + 'person5', + 'person2', + 'person76', + 'person20', + 'person17', + 'person23', + 'person31', + 'person30', + 'person29', + 'person28', + 'person27', + 'person26', + 'person25', + 'person24', + ], + text: 'Blueman Group', + }, + { + _id: 'id2', + eventId: 'tsfdsf', + studentIds: [], + text: 'Romeo und Julia', + }, + { + _id: 'id3', + eventId: '', + studentIds: [], + text: 'Keins von beiden', + }, + ], + }, + { + _id: 'id1', + text: 'Wählt eine Veranstaltung!', + choices: [ + { + _id: 'id1', + eventId: 'poll1', + studentIds: [ + 'person5', + 'person2', + 'person76', + 'person20', + 'person17', + 'person23', + 'person31', + 'person30', + 'person29', + 'person28', + 'person27', + 'person26', + 'person25', + 'person24', + ], + text: 'Planspiel Bundestag', + }, + { + _id: 'id2', + eventId: 'P', + studentIds: [], + text: 'Planspiel Bundesrat', + }, + { + _id: 'id3', + eventId: '', + studentIds: [], + text: 'Planspiel 3', + }, + ], + }, +]; + +export { polls }; + +const project: Project = { + _id: 'ProjectId', + name: 'Berlin 2024', + idsThatAreRequiredForEveryone: [ + 'group1', + 'group2', + 'group3', + 'solo2', + 'solo3', + 'solo4', + 'solo5', + ], + relatedPolls: ['id0', 'id1'], +}; + +export { project, Project }; +const students: Student[] = [ + { _id: 'person1' }, + { _id: 'person2' }, + { _id: 'person3' }, + { _id: 'person4' }, + { _id: 'person5' }, + { _id: 'person6' }, + { _id: 'person7' }, + { _id: 'person8' }, + { _id: 'person9' }, + { _id: 'person10' }, + { _id: 'person11' }, + { _id: 'person12' }, + { _id: 'person13' }, + { _id: 'person14' }, + { _id: 'person15' }, + { _id: 'person16' }, + { _id: 'person17' }, + { _id: 'person18' }, + { _id: 'person19' }, + { _id: 'person20' }, + { _id: 'person21' }, + { _id: 'person22' }, + { _id: 'person23' }, + { _id: 'person24' }, + { _id: 'person25' }, + { _id: 'person26' }, + { _id: 'person27' }, + { _id: 'person28' }, + { _id: 'person29' }, + { _id: 'person30' }, + { _id: 'person31' }, + { _id: 'person32' }, + { _id: 'person33' }, + { _id: 'person34' }, + { _id: 'person35' }, + { _id: 'person36' }, + { _id: 'person37' }, + { _id: 'person38' }, + { _id: 'person39' }, + { _id: 'person40' }, + { _id: 'person41' }, + { _id: 'person42' }, + { _id: 'person43' }, + { _id: 'person44' }, + { _id: 'person45' }, + { _id: 'person46' }, + { _id: 'person47' }, + { _id: 'person48' }, + { _id: 'person49' }, + { _id: 'person50' }, + { _id: 'person51' }, + { _id: 'person52' }, + { _id: 'person53' }, + { _id: 'person54' }, + { _id: 'person55' }, + { _id: 'person56' }, + { _id: 'person57' }, + { _id: 'person58' }, + { _id: 'person59' }, + { _id: 'person60' }, + { _id: 'person61' }, + { _id: 'person62' }, + { _id: 'person63' }, + { _id: 'person64' }, + { _id: 'person65' }, + { _id: 'person66' }, + { _id: 'person67' }, + { _id: 'person68' }, + { _id: 'person69' }, + { _id: 'person70' }, + { _id: 'person71' }, + { _id: 'person72' }, + { _id: 'person73' }, + { _id: 'person74' }, + { _id: 'person75' }, + { _id: 'person76' }, + { _id: 'person77' }, + { _id: 'person78' }, + { _id: 'person79' }, + { _id: 'person80' }, + { _id: 'person81' }, + { _id: 'person82' }, + { _id: 'person83' }, + { _id: 'person84' }, + { _id: 'person85' }, + { _id: 'person86' }, + { _id: 'person87' }, + { _id: 'person88' }, + { _id: 'person89' }, + { _id: 'person90' }, + { _id: 'person91' }, + { _id: 'person92' }, + { _id: 'person93' }, + { _id: 'person94' }, + { _id: 'person95' }, + { _id: 'person96' }, + { _id: 'person97' }, + { _id: 'person98' }, + { _id: 'person99' }, + { _id: 'person100' }, +]; + +export { students }; diff --git a/test/timeDistribution.test.ts b/test/timeDistribution.test.ts index 4a79624..cfc8107 100644 --- a/test/timeDistribution.test.ts +++ b/test/timeDistribution.test.ts @@ -5,9 +5,11 @@ import { getVotingIds, } from '../src/alg/TimeDistribution/Utils'; import { items, polls, students, project } from './data'; +import { items as failedItems } from './failData'; describe('Time Distribution Algorithm', () => { - const allocationResult = main(items, students, project, polls); + main(items, students, project, polls); + const allocationResult = items; it('should allocate the correct number of items to each student', () => { const requiredIdsLength = getDefaultIds(project).length; @@ -86,4 +88,8 @@ describe('Time Distribution Algorithm', () => { } }); }); + it('should return false when no solution is found', () => { + const result = main(failedItems, students, project, polls); + expect(result).toBe(false); + }); });