import { Doc, FieldType } from "../../../../../fields/Doc"; import { Docs } from "../../../../documents/Documents"; import { Col } from "./DocCreatorMenu"; import { DynamicField } from "./FieldTypes/DynamicField"; import { Field, FieldSettings, ViewType } from "./FieldTypes/Field"; import { } from "./FieldTypes/FieldUtils"; import { } from "./FieldTypes/StaticField"; export class Template { mainField: DynamicField; settings: FieldSettings; constructor(templateInfo: FieldSettings) { this.mainField = this.setupMainField(templateInfo); this.settings = templateInfo; } get childFields(): Field[] { return this.mainField.getSubfields }; get allFields(): Field[] { return this.mainField.getAllSubfields }; get contentFields(): Field[] { return this.allFields.filter(field => field.getViewType === ViewType.STATIC) }; get doc(){ return this.mainField.renderedDoc(); }; cloneBase = () => { const clone: Template = new Template(this.settings); clone.allFields.forEach(field => { const matchingField: Field = this.allFields.filter(f => f.getID === field.getID)[0]; matchingField.applyAttributes(field); }) return clone; } getRenderedDoc = () => { const doc: Doc = this.mainField.renderedDoc(); this.contentFields.forEach(field => { const title: string = field.getTitle(); const val: FieldType = field.getContent() as FieldType; if (!title || !val) return; doc[title] = val; }); return doc; } getFieldByID = (id: number): Field => { return this.allFields.filter(field => field.getID === id)[0]; } getFieldByTitle = (title: string) => { return this.allFields.filter(field => field.getTitle() === title)[0]; } setupMainField = (templateInfo: FieldSettings) => { return new DynamicField(templateInfo, 1); } get descriptionSummary(): string { let summary: string = ''; this.contentFields.forEach(field => { summary += `--- Field #${field.getID} (title: ${field.getTitle()}): ${field.getDescription ?? ''} ---`; }); return summary; } get compiledContent(): string { let summary: string = ''; this.contentFields.forEach(field => { summary += `--- Field #${field.getID} (title: ${field.getTitle()}): ${field.getContent() ?? ''} ---`; }); return summary; } renderUpdates = () => { this.allFields.forEach(field => { field.updateRenderedDoc(field.renderedDoc()); }); }; resetToBase = () => { this.allFields.forEach(field => { field.updateRenderedDoc(); }) } isValidTemplate = (cols: Col[]) => { const matches: number[][] = this.getMatches(cols); const maxMatches: number = this.maxMatches(matches); return maxMatches === this.contentFields.length; } getMatches = (cols: Col[]): number[][] => { const numFields = this.contentFields.length; if (cols.length !== numFields) return []; const matches: number[][] = Array(numFields) .fill([]) .map(() => []); this.contentFields.forEach((field, i) => { matches[i] = (field.matches(cols)); }); return matches; } maxMatches = (matches: number[][]) => { if (matches.length === 0) return 0; const fieldsCt = this.contentFields.length; const used: boolean[] = Array(fieldsCt).fill(false); const mt: number[] = Array(fieldsCt).fill(-1); const augmentingPath = (v: number): boolean => { if (used[v]) return false; used[v] = true; for (const to of matches[v]) { if (mt[to] === -1 || augmentingPath(mt[to])) { mt[to] = v; return true; } } return false; }; for (let v = 0; v < fieldsCt; ++v) { used.fill(false); augmentingPath(v); } let count: number = 0; for (let i = 0; i < fieldsCt; ++i) { if (mt[i] !== -1) ++count; } return count; }; }