Skip to content

Commit 1e202b9

Browse files
committed
Reimplemented error highlighting using string matching
1 parent 7d47991 commit 1e202b9

9 files changed

Lines changed: 62 additions & 124 deletions

File tree

solves/base-template/internals/global.d.ts renamed to solves/base-template/internals/global.d.ts.ejs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Asset Handling
3+
*/
4+
15
declare module '*.svg' {
26
const src: string;
37
export default src;
@@ -28,3 +32,19 @@ declare module '*.lp' {
2832
export default src;
2933
}
3034

35+
/*
36+
* General
37+
*/
38+
39+
type BaseInputKeys = <%-
40+
Object.entries(inputBase).map(([k, v]) =>
41+
`"${k}"`
42+
).join(" | ")
43+
-%>;
44+
type ConstrainedInputKeys = <%-
45+
Object.entries(inputConstrained).map(([k, v]) =>
46+
`"${k}"`
47+
).join(" | ")
48+
-%>;
49+
type AllInputKeys = BaseInputKeys | ConstrainedInputKeys;
50+

solves/base-template/src/components/App.tsx.ejs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,7 @@ interface State {
2626
-%>
2727

2828
outputResult: null | ClingoResult;
29-
invalidInputLines: {
30-
<%-
31-
Object.entries({...inputBase, ...inputConstrained}).map(([k, v]) => {
32-
const x = {};
33-
x.inputID = k;
34-
return ht.stateTypeInputValidation(x);
35-
}).join("")
36-
-%>
37-
};
29+
invalidInputs: Map<AllInputKeys, Set<string>>;
3830
}
3931

4032
export class App extends React.Component<{}, State> {
@@ -62,33 +54,23 @@ export class App extends React.Component<{}, State> {
6254
-%>
6355

6456
outputResult: null,
65-
invalidInputLines: {
66-
<%-
67-
Object.entries({...inputBase, ...inputConstrained}).map(([k, v]) => {
68-
const x = {};
69-
x.inputID = k;
70-
x.initialValues = v.initialValues;
71-
return ht.stateInputValidation(x);
72-
}).join("")
73-
-%>
74-
},
57+
invalidInputs: new Map(),
7558
};
7659
}
7760

7861
async _recalculateOutputs() {
7962
const result = await runSolver({
8063
<%-
81-
Object.entries({...inputBase, ...inputConstrained}).map(([k, v]) => {
82-
const x = {};
83-
x.inputID = k;
84-
return ht.resultParameter(x);
85-
}).join("")
86-
-%>
64+
Object.entries({...inputBase, ...inputConstrained}).map(([k, v]) =>
65+
" " +
66+
`${k}: parseInput(this.state.input${upperCaseFirst(k)}),`
67+
).join("\n")
68+
%>
8769
});
8870
this.setState({
89-
initialized: true,
90-
outputResult: result.resultObj,
91-
invalidInputLines: result.invalidInputs,
71+
initialized: true,
72+
outputResult: result.resultObj,
73+
invalidInputs: result.invalidConstantTuples,
9274
});
9375
}
9476

@@ -112,10 +94,8 @@ export class App extends React.Component<{}, State> {
11294
<%-
11395
Object.entries({...inputBase, ...inputConstrained}).map(([k, v]) => {
11496
const x = {};
97+
x.inputID = k;
11598
x.title = v.title;
116-
x.stateValue = "input" + upperCaseFirst(k);
117-
x.stateValidation = k;
118-
x.onChangeFnName = "set" + upperCaseFirst(k);
11999
return ht.jsxParts(x);
120100
}).join("")
121101
-%>
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<div className="text-input-wrapper">
22
<LineHighlighterTextbox
33
label="<%- title %>"
4-
initialValue={this.state.<%- stateValue %>}
5-
errorLineNumbers={this.state.invalidInputLines.<%- stateValidation %>}
6-
onChange={<%- onChangeFnName %>}
4+
initialValue={this.state.input<%- upperCaseFirst(inputID) %>}
5+
invalidLines={
6+
this.state.invalidInputs.get("<%- inputID %>") || new Set()
7+
}
8+
onChange={set<%- upperCaseFirst(inputID) %>}
79
/>
810
</div>

solves/base-template/src/components/App.tsx.ejshelpers/resultParameter.tsx.ejs

Lines changed: 0 additions & 1 deletion
This file was deleted.

solves/base-template/src/components/App.tsx.ejshelpers/stateInputValidation.tsx.ejs

Lines changed: 0 additions & 1 deletion
This file was deleted.

solves/base-template/src/components/App.tsx.ejshelpers/stateTypeInputValidation.tsx.ejs

Lines changed: 0 additions & 1 deletion
This file was deleted.

solves/base-template/src/components/generic/LineHighlighterTextbox/index.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import "codemirror/lib/codemirror.css";
1919
import "./index.css";
2020

2121
interface Props {
22-
label: string;
23-
initialValue: string;
24-
errorLineNumbers: number[];
25-
onChange: (event: {target: {value: string;};}) => Promise<void>;
22+
label: string;
23+
initialValue: string;
24+
invalidLines: Set<string>;
25+
onChange: (event: {target: {value: string;};}) => Promise<void>;
2626
}
2727

2828
interface State {
@@ -99,8 +99,10 @@ export class LineHighlighterTextbox extends React.Component<Props, State> {
9999
return;
100100
}
101101

102-
for (const line of this.props.errorLineNumbers) {
103-
this.cmInstance.addLineClass(line, "wrap", "cm-invalid-line");
102+
for (const [i, line] of this.getValue().split("\n").entries()) {
103+
if (this.props.invalidLines.has(line.trim())) {
104+
this.cmInstance.addLineClass(i, "wrap", "cm-invalid-line");
105+
}
104106
}
105107
}
106108

solves/base-template/src/runSolver/index.ts.ejs

Lines changed: 18 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,14 @@ import validationSpecStr from "./validationSpec.lp";
88

99
export type ClingoResult = _ClingoResult;
1010

11-
type BaseInputKeys = "colour" | "vertex";
12-
type ConstrainedInputKeys = "edge";
13-
//type AllInputKeys = BaseInputKeys | ConstrainedInputKeys;
14-
1511
const reConstant = /^[a-z][a-zA-Z0-9]*$/;
1612

17-
function mergeIndexLists(a: number[], b: number[]): number[] {
18-
const indexSet: Set<number> = new Set<number>(a.concat(b));
19-
return Array.from(indexSet);
20-
}
21-
2213
/*** ***/
2314

2415
interface GeneratedClingoFacts {
2516
clingoFacts: ReadonlyMap<string, string>; // Map<clingo fact, constant tuple>
2617
invalidConstants: number[];
27-
invalidConstantTuples: ReadonlySet<string>;
18+
invalidConstantTuples: Set<string>;
2819
}
2920

3021
function generateClingoFacts(
@@ -118,36 +109,6 @@ async function getConstantTuplesThatFailConstraints(
118109
return ret;
119110
}
120111

121-
// TODO: Delete this
122-
async function getInvalidEdgeFacts(
123-
problemInstance: string,
124-
edgeFacts: string[],
125-
): Promise<number[]> {
126-
// Use Clingo to get all invalid facts
127-
const fullQuery = [
128-
problemInstance,
129-
validationSpecStr,
130-
].join("\n\n");
131-
const result = await runClingo(fullQuery);
132-
133-
if (result.solution === null) {
134-
throw new Error("runClingo() returned a null solution.");
135-
}
136-
137-
// Create a set of invalid facts as strings, with whitespace removed
138-
const op = (x: string) => (x.replaceAll(/\s/g, "") + ".");
139-
const invalidEdgeFacts: Set<string> = new Set(result.solution.map(op));
140-
141-
// TODO: Refactor to something nicer than a loop.
142-
const invalidIndices: number[] = [];
143-
for (const [i, edgeFact] of edgeFacts.entries()) {
144-
if (invalidEdgeFacts.has(edgeFact.replaceAll(/\s/g, ""))) {
145-
invalidIndices.push(i);
146-
}
147-
}
148-
return invalidIndices;
149-
}
150-
151112
/*** ***/
152113

153114
export interface SolverParameters {
@@ -164,17 +125,7 @@ export interface SolverResult {
164125
// Clingo-specific output.
165126
// TODO: Make SolverResult backend-agnostic!
166127
resultObj: null | ClingoResult;
167-
invalidInputs: {
168-
// These are lists of integers, where each integer is an index of
169-
// an invalid string within the corresponding input list.
170-
<%-
171-
Object.entries({...inputBase, ...inputConstrained}).map(([k, v]) => {
172-
const x = {};
173-
x.inputID = k;
174-
return ht.resultType(x);
175-
}).join("")
176-
-%>
177-
};
128+
invalidConstantTuples: Map<AllInputKeys, Set<string>>;
178129
}
179130

180131
export async function runSolver(params: SolverParameters): Promise<SolverResult> {
@@ -195,36 +146,22 @@ export async function runSolver(params: SolverParameters): Promise<SolverResult>
195146
%>
196147
]);
197148

198-
const tmpColourFacts = baseFacts.get("colour");
199-
const tmpVertexFacts = baseFacts.get("vertex");
200-
const tmpEdgeFacts = constrainedFacts.get("edge");
201-
if (tmpColourFacts === undefined) throw "temporary1";
202-
if (tmpVertexFacts === undefined) throw "temporary2";
203-
if (tmpEdgeFacts === undefined) throw "temporary3";
204-
205149
const problemInstance: string = [...baseFacts, ...constrainedFacts]
206150
.map(([_, v]) => [...v.clingoFacts.keys()].join("\n"))
207151
.join("\n");
208152

209-
console.log(await getConstantTuplesThatFailConstraints(
210-
problemInstance,
211-
constrainedFacts,
212-
));
213-
214-
const invalidEdgeFactIndices: number[] = await getInvalidEdgeFacts(
215-
problemInstance,
216-
[...tmpEdgeFacts.clingoFacts.keys()],
217-
);
218-
219-
const totalInvalidEdgeFacts: number[] = mergeIndexLists(
220-
tmpEdgeFacts.invalidConstants,
221-
invalidEdgeFactIndices,
153+
const constTupConstraintFailures: Map<AllInputKeys, Set<string>> = (
154+
await getConstantTuplesThatFailConstraints(
155+
problemInstance,
156+
constrainedFacts,
157+
)
222158
);
223159

224160
const resultObj: null | ClingoResult = await (async()=>{
225161
const noInvalidConstantTups = [...baseFacts, ...constrainedFacts]
226162
.every(([_, v]) => (v.invalidConstantTuples.size === 0));
227-
const validAgainstConstraints = (invalidEdgeFactIndices.length === 0);
163+
const validAgainstConstraints = [...constTupConstraintFailures]
164+
.every(([_, v]) => (v.size === 0));
228165

229166
if (noInvalidConstantTups && validAgainstConstraints) {
230167
const fullQuery = [
@@ -237,13 +174,14 @@ export async function runSolver(params: SolverParameters): Promise<SolverResult>
237174
}
238175
})();
239176

240-
return {
241-
resultObj: resultObj,
242-
invalidInputs: {
243-
colour: tmpColourFacts.invalidConstants,
244-
vertex: tmpVertexFacts.invalidConstants,
245-
edge: totalInvalidEdgeFacts,
246-
},
247-
};
177+
const invalidConstantTuples: Map<AllInputKeys, Set<string>> = new Map(
178+
[...baseFacts, ...constrainedFacts].map(([inputID, factsObj]) => {
179+
const constTups = factsObj.invalidConstantTuples;
180+
const s = constTupConstraintFailures.get(inputID);
181+
if (s !== undefined) [...s].forEach(x => constTups.add(x));
182+
return [inputID, constTups];
183+
}),
184+
);
185+
return {resultObj, invalidConstantTuples};
248186
}
249187

solves/base-template/src/runSolver/index.ts.ejshelpers/resultType.ts.ejs

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)