import { OutputResponse } from "./types"; import { Context, Output } from "./definitions"; export function getPerfectMatch( config: Output, outputs: OutputResponse[], ): OutputResponse | null { return ( outputs.find( ({ make, model, serial }) => make === config.make && model === config.model && serial === config.serial, ) ?? null ); } export function getNamePreferences( outputs: OutputResponse[], config: Output, ): (OutputResponse | null)[] { return Array.from( { length: config.names?.length ?? 0 }, (_, idx) => outputs.find(({ name }) => config.names?.[idx] === name) ?? null, ); } export enum OutputScore { ID_MATCH = 3, NAME_MATCH = 2, WILDCARD_MATCH = 1, NO_MATCH = 0, } export function computeGroupScore( config: Output, output: OutputResponse | OutputResponse[], ) { if (getPerfectMatch(config, [output].flat())) { return OutputScore.ID_MATCH; } const preferences = getNamePreferences([output].flat(), config); if (preferences.some((preference) => preference !== null)) { return OutputScore.NAME_MATCH; } if (config.names?.includes("*")) { return OutputScore.WILDCARD_MATCH; } return OutputScore.NO_MATCH; } export function computeContextScore( config: Context, outputs: OutputResponse[], ): [score: number, outputMap: Map | undefined] { let score = 0; const map = new Map(); const outputSet = new Set(outputs); const usedGroups = new Set(); Object.values(config.outputs).forEach((output) => { const match = getPerfectMatch(output, Array.from(outputSet)); if (match === null || output.group === undefined) { return; } console.log( `ID_MATCH for group "${output.group}" on output "${match.name}"`, ); score += OutputScore.ID_MATCH; outputSet.delete(match); usedGroups.add(output); map.set(output.group, match); }); let groups = config.outputs.filter((group) => !usedGroups.has(group)); if (groups.length === 0) return [score, map] as const; outputs = Array.from(outputSet); const preferences = groups.map(getNamePreferences.bind(null, outputs)); const maxPreferences = Math.max(...preferences.map(({ length }) => length)); Array.from({ length: maxPreferences }, (_, idx) => preferences.forEach((preference, jdx) => { if ( idx < preference.length && preference[idx] !== null && outputSet.has(preference[idx]) && groups[jdx].group !== undefined ) { console.log( `NAME_MATCH for group "${groups[jdx].group}" on output "${preference[idx].name}"`, ); score += OutputScore.NAME_MATCH; outputSet.delete(preference[idx]); usedGroups.add(groups[jdx]); map.set(groups[jdx].group, preference[idx]); } }), ); groups = groups.filter((group) => !usedGroups.has(group)); if (groups.length > 1) { return [0, undefined]; } else if (groups.length === 0) { return [score, map]; } else if (groups[0].group !== undefined && groups[0].names?.includes("*")) { map.set(groups[0].group, Array.from(outputSet)[0]); console.log( `WILDCARD_MATCH for group "${groups[0].group}" on output "${map.get(groups[0].group)}"`, ); return [score + OutputScore.WILDCARD_MATCH, map]; } else { return [0, undefined]; } }