improvement: new prosthesis type data structure implemented and finally working!
This commit is contained in:
@@ -9,3 +9,87 @@ export function normalizeTaskTeeth(value: Prisma.JsonValue | null | undefined):
|
||||
.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')
|
||||
.map((v) => String(v));
|
||||
}
|
||||
|
||||
export function sortProsthesisTeeth(teeth: readonly string[]): string[] {
|
||||
return [...teeth].sort((a, b) => {
|
||||
const rank = (tooth: string) => (tooth === 'UA' ? 0 : tooth === 'LA' ? 1 : 2);
|
||||
const diff = rank(a) - rank(b);
|
||||
if (diff !== 0) return diff;
|
||||
return a.localeCompare(b, undefined, { numeric: true });
|
||||
});
|
||||
}
|
||||
|
||||
/** Group ids that span more than one tooth (bridges). */
|
||||
export function connectedSelectionGroupIds(
|
||||
rows: Array<{
|
||||
selectionGroupId?: string | null;
|
||||
tooth?: string;
|
||||
teeth?: Prisma.JsonValue;
|
||||
}>,
|
||||
): Set<string> {
|
||||
const byGroup = new Map<string, Set<string>>();
|
||||
for (const row of rows) {
|
||||
const id = row.selectionGroupId?.trim();
|
||||
if (!id) continue;
|
||||
const teeth =
|
||||
row.tooth != null && row.tooth !== ''
|
||||
? [row.tooth]
|
||||
: normalizeTaskTeeth(row.teeth);
|
||||
const set = byGroup.get(id) ?? new Set<string>();
|
||||
for (const tooth of teeth) set.add(tooth);
|
||||
byGroup.set(id, set);
|
||||
}
|
||||
const connected = new Set<string>();
|
||||
for (const [id, teeth] of byGroup) {
|
||||
if (teeth.size > 1) connected.add(id);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
export function aggregateProsthesisGroupsFromTasks(
|
||||
tasks: Array<{
|
||||
prosthesisTypeCode: string;
|
||||
teeth: Prisma.JsonValue;
|
||||
selectionGroupId?: string | null;
|
||||
}>,
|
||||
): Array<{
|
||||
prosthesisTypeCode: string;
|
||||
teeth: string[];
|
||||
connected?: boolean;
|
||||
selectionGroupId?: string;
|
||||
}> {
|
||||
const connectedIds = connectedSelectionGroupIds(tasks);
|
||||
const byKey = new Map<
|
||||
string,
|
||||
{ prosthesisTypeCode: string; teeth: string[]; selectionGroupId: string }
|
||||
>();
|
||||
|
||||
for (const task of tasks) {
|
||||
if (!task.prosthesisTypeCode) continue;
|
||||
const selectionGroupId = task.selectionGroupId?.trim() ?? '';
|
||||
const teeth = normalizeTaskTeeth(task.teeth);
|
||||
const key = `${teeth.join(',')}::${task.prosthesisTypeCode}`;
|
||||
const entry = byKey.get(key) ?? {
|
||||
prosthesisTypeCode: task.prosthesisTypeCode,
|
||||
teeth: [],
|
||||
selectionGroupId,
|
||||
};
|
||||
entry.teeth.push(...teeth);
|
||||
if (!entry.selectionGroupId && selectionGroupId) {
|
||||
entry.selectionGroupId = selectionGroupId;
|
||||
}
|
||||
byKey.set(key, entry);
|
||||
}
|
||||
|
||||
return [...byKey.values()]
|
||||
.map((group) => {
|
||||
const teeth = sortProsthesisTeeth([...new Set(group.teeth)]);
|
||||
return {
|
||||
prosthesisTypeCode: group.prosthesisTypeCode,
|
||||
teeth,
|
||||
selectionGroupId: group.selectionGroupId || undefined,
|
||||
connected: Boolean(group.selectionGroupId) && connectedIds.has(group.selectionGroupId),
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.prosthesisTypeCode.localeCompare(b.prosthesisTypeCode));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user