Move hard conflict and oversized group detection from JS to server
This commit is contained in:
@@ -82,90 +82,8 @@ async function loadStudents() {
|
||||
lastOveralls = allOveralls;
|
||||
|
||||
const mismatchList = constraintData.mismatches;
|
||||
|
||||
const studentName = {};
|
||||
for (const s of students) studentName[s.id] = s.name;
|
||||
|
||||
const mustAdj = {};
|
||||
for (const s of students) {
|
||||
for (const [bId, eff] of Object.entries(allOveralls[s.id])) {
|
||||
if (eff.kind === 'must') {
|
||||
const a = s.id, b = parseInt(bId);
|
||||
if (!mustAdj[a]) mustAdj[a] = [];
|
||||
mustAdj[a].push(b);
|
||||
if (!mustAdj[b]) mustAdj[b] = [];
|
||||
mustAdj[b].push(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ufParent = {};
|
||||
for (const s of students) ufParent[s.id] = s.id;
|
||||
const ufFind = (x) => {
|
||||
if (ufParent[x] !== x) ufParent[x] = ufFind(ufParent[x]);
|
||||
return ufParent[x];
|
||||
};
|
||||
for (const s of students) {
|
||||
for (const [bId, eff] of Object.entries(allOveralls[s.id])) {
|
||||
if (eff.kind === 'must') {
|
||||
const ra = ufFind(s.id), rb = ufFind(parseInt(bId));
|
||||
if (ra !== rb) ufParent[ra] = rb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const findMustPath = (from, to) => {
|
||||
if (from === to) return [from];
|
||||
const visited = new Set([from]);
|
||||
const queue = [[from]];
|
||||
while (queue.length > 0) {
|
||||
const path = queue.shift();
|
||||
const curr = path[path.length - 1];
|
||||
for (const next of (mustAdj[curr] || [])) {
|
||||
if (next === to) return [...path, next];
|
||||
if (!visited.has(next)) {
|
||||
visited.add(next);
|
||||
queue.push([...path, next]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const hardConflictList = [];
|
||||
for (const s of students) {
|
||||
for (const [bId, eff] of Object.entries(allOveralls[s.id])) {
|
||||
if (eff.kind !== 'must_not') continue;
|
||||
const b = parseInt(bId);
|
||||
if (ufFind(s.id) !== ufFind(b)) continue;
|
||||
const path = findMustPath(b, s.id);
|
||||
if (!path) continue;
|
||||
const chain = [];
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
const x = path[i], y = path[i + 1];
|
||||
if (allOveralls[x]?.[y]?.kind === 'must') {
|
||||
chain.push({ from: studentName[x], to: studentName[y], kind: 'must' });
|
||||
} else {
|
||||
chain.push({ from: studentName[y], to: studentName[x], kind: 'must' });
|
||||
}
|
||||
}
|
||||
chain.push({ from: s.name, to: studentName[b], kind: 'must_not' });
|
||||
hardConflictList.push(chain);
|
||||
}
|
||||
}
|
||||
|
||||
const mustGroups = {};
|
||||
for (const s of students) {
|
||||
const root = ufFind(s.id);
|
||||
if (!mustGroups[root]) mustGroups[root] = [];
|
||||
mustGroups[root].push(s.name);
|
||||
}
|
||||
const oversizedGroups = [];
|
||||
for (const members of Object.values(mustGroups)) {
|
||||
if (members.length > trip.room_size) {
|
||||
oversizedGroups.push(members);
|
||||
}
|
||||
}
|
||||
const hardConflictList = constraintData.hard_conflicts;
|
||||
const oversizedGroups = constraintData.oversized_groups;
|
||||
|
||||
const conflictsEl = document.getElementById('conflicts');
|
||||
const conflictsWasOpen = conflictsEl.querySelector('wa-details')?.open;
|
||||
|
||||
Reference in New Issue
Block a user