1 | sclass BEACalculations { |
2 | GazelleBEA mod; |
3 | *(GazelleBEA *mod) {} |
4 | |
5 | transient int liveOutputDelay = 1000; |
6 | transient double algoTimeout = 30.0; |
7 | |
8 | void reactAllInputsWithSomePatterns() { |
9 | for (BEAObject input : mod.beaObjectsOfType("input")) { |
10 | new ReactInputWithSomePatterns r; |
11 | r.input = input; |
12 | r.ccOut = db_mainConcepts(); |
13 | r.max = 10; |
14 | r.start(); |
15 | stepAllWithTimeout(10.0, r); |
16 | } |
17 | } |
18 | |
19 | void reactAllInputsWithAllSyntacticPatterns() { |
20 | for ping (BEA input : mod.beaList("input")) { |
21 | for ping (BEA pattern : mod.beaList("Syntactic Pattern")) { |
22 | continue if patternAlwaysMatches(pattern); |
23 | reactInputWithPattern(input, pattern); |
24 | } |
25 | } |
26 | } |
27 | |
28 | void reactAllInputsWithPattern(BEA pattern) { |
29 | for ping (BEA input : mod.beaList("input")) |
30 | reactInputWithPattern(input, pattern); |
31 | } |
32 | |
33 | bool patternAlwaysMatches(BEA pat) { |
34 | ret isTrue_getOpt alwaysMatches(pat); |
35 | } |
36 | |
37 | class ReactInputWithSomePatterns implements Steppable { |
38 | BEAObject input; |
39 | Concepts ccOut; |
40 | int max = 3, n; |
41 | Iterator<BEAObject> patterns; |
42 | |
43 | void start { |
44 | n = countConceptsWhereIC(ccOut, BEAObject, +input, type := "match"); |
45 | patterns = iterator(sortByConceptID(conceptsWhereIC BEAObject(type := "Pattern"))); |
46 | } |
47 | |
48 | public bool step() { |
49 | if (n >= max) false; |
50 | if (!patterns.hasNext()) false; |
51 | if (reactInputWithPattern(input, patterns.next(), ccOut) != null) |
52 | ++n; |
53 | true; |
54 | } |
55 | } |
56 | |
57 | // (patern, mapping) |
58 | Pair<BEA, SS> matchInputWithPatternList(S text, BEA patternList) { |
59 | L<BEA> patterns = cast cget patterns(patternList); |
60 | fOr (BEA pattern : patterns) { |
61 | SS mapping = matchInputWithPattern(text, pattern); |
62 | if (mapping != null) ret pair(pattern, mapping); |
63 | } |
64 | null; |
65 | } |
66 | |
67 | // we don't do this anymore |
68 | new ThreadLocal<Bool> matchInput_droppedPunctuation; |
69 | |
70 | SS matchInputWithPattern(BEAObject input, BEAObject pattern) { |
71 | S text = getString text(input); |
72 | ret matchInputWithPattern(text, pattern); |
73 | } |
74 | |
75 | SS matchInputWithPattern(S text, BEAObject pattern) { |
76 | S pat = getString text(pattern); |
77 | bool punctuationOnly = isTrue_getOpt punctuationOnly(pattern); |
78 | |
79 | if (pattern.typeIs("Syntactic Pattern")) |
80 | ret matchInputWithSyntacticPattern(text, pat, punctuationOnly); |
81 | else if (eqic_gen(pattern~.subType, "PhraseCache")) |
82 | ret phraseCache(pat, text) ? litmap() : null; |
83 | else |
84 | ret matchInputWithPattern(text, pat, punctuationOnly); |
85 | } |
86 | |
87 | SS matchInputWithSyntacticPattern(S text, S pat, bool punctuationOnly default false) { |
88 | pat = starsToAngleBracketedNumbers(pat); |
89 | ret matchInputWithPattern(text, pat, punctuationOnly); |
90 | } |
91 | |
92 | SS matchInputWithPattern(S text, S pat, bool punctuationOnly default false) { |
93 | SS mapping = flexMatchAngleBracketVarsIC_honorPunctuation_noBrackets_first(pat, text); |
94 | if (mapping != null || punctuationOnly) ret mapping; |
95 | /*matchInput_droppedPunctuation.set(true); |
96 | ret flexMatchAngleBracketVarsIC_first(pat, text);*/ |
97 | null; // not doing the implicit punctuation drop anymore (it's now an explicit pattern) |
98 | } |
99 | |
100 | BEAObject reactInputWithPattern(BEAObject input, BEAObject pattern, Concepts ccOut default db_mainConcepts()) { |
101 | if (input == null || pattern == null) null; |
102 | matchInput_droppedPunctuation.set(false); |
103 | SS mapping = matchInputWithPattern(input, pattern); |
104 | //printVars_str("reactInputWithPattern", +input, +pattern, +mapping); |
105 | if (mapping == null) null; |
106 | BEA match = uniqCI(ccOut, BEA, |
107 | type := "Match", |
108 | +input, |
109 | +pattern); |
110 | cset(match, |
111 | +mapping, |
112 | droppedPunctuation := trueOrNull(matchInput_droppedPunctuation!), |
113 | ); |
114 | ret match; |
115 | } |
116 | |
117 | O serveAnalyzeInput(GazelleBEA.Req req) { |
118 | new Concepts ccOut; |
119 | BEAObject input = getConcept BEAObject(parseLong(req.get("id"))); |
120 | if (input == null) |
121 | input = cnew(ccOut, BEAObject, type := "Input", text := req.get("q")); |
122 | S text = getString text(input); |
123 | new ReactInputWithSomePatterns r; |
124 | r.input = input; |
125 | r.ccOut = ccOut; |
126 | r.max = 1000; |
127 | r.start(); |
128 | stepAllWithTimeout(10.0, r); |
129 | Cl matches = conceptsWhereIC(ccOut, BEAObject, type := "Match"); |
130 | ret h1_title("Analyze Input") |
131 | + p("Input: " + b(htmlEncode_nlToBr_withIndents(text))) |
132 | + p(empty(matches) ? "No matches" : "Matches") |
133 | + ul_htmlEncode(matches); |
134 | } |
135 | |
136 | O serveQueryPage(GazelleBEA.Req req, bool withFrame default false) { |
137 | S q = req.get("q"), algorithm = req.get("algorithm"); |
138 | bool dontRun = eq(req.get("dontRun"), "1"); |
139 | bool liveOutput = eq(req.get("liveOutput"), "1"); |
140 | if (liveOutput) req.noSpam(); |
141 | |
142 | if (eqic(algorithm, "process input")) |
143 | algorithm = "Process new input v3"; |
144 | |
145 | //if (liveOutput) ret jsonEncode(litmap(answer := "Live output demo: " + htmlEncode2(q))); |
146 | |
147 | Map<S, IF0<Algorithm>> algorithms = algorithms(); |
148 | |
149 | S output = empty(algorithm) || dontRun ? null : doAlgorithm(algorithms, algorithm, q, liveOutput); |
150 | |
151 | if (liveOutput) |
152 | ret jsonEncode(litorderedmap(answer := output)); |
153 | |
154 | S right = withFrame ? "" : mod.html_loggedIn(); |
155 | |
156 | Algorithm alg = callF(lookupPossiblyCI(algorithms, algorithm)); |
157 | if (alg != null) { |
158 | alg.q = q; |
159 | alg.req = mod.currentReq(); |
160 | } |
161 | |
162 | S centered = |
163 | (withFrame ? "" : htitle_h2(ahref(mod.baseLink + "/", "Gazelle") + " Query" |
164 | + htmlEncode2((empty(q) ? "" : ": " + q) |
165 | + appendSquareBracketed(algorithm)))) |
166 | + hscript(replaceVars([[ |
167 | var sugLoading = false, sugTriggerAgain = false; |
168 | |
169 | function sugTrigger() { |
170 | console.log("sugTrigger"); |
171 | if (sugLoading) { sugTriggerAgain = true; return; } |
172 | |
173 | // get form data as JSON |
174 | |
175 | var data = { |
176 | "liveOutput" : "1", |
177 | "q": $("textarea[name=q]").val(), |
178 | "algorithm": $("select[name=algorithm]").val(), |
179 | "algorithmID": $("select[name=algorithmID]").val(), // XXX: do this for all additional alg parameters |
180 | }; |
181 | |
182 | const url = "/query"; |
183 | console.log("Loading " + url + " with " + data); |
184 | sugLoading = true; |
185 | $.post(url, data, |
186 | function(result) { |
187 | console.log("Suggestor result: " + result); |
188 | const answer = !result ? "" : JSON.parse(result).answer; |
189 | if (answer) { |
190 | $("#liveResult .sectionContents").html(answer); |
191 | $("#liveResult").show(); |
192 | } else |
193 | $("#liveResult").hide(); |
194 | //$("#suggestorResult").html(answer ? "Suggestor says: " + answer : ""); |
195 | } |
196 | ).always(function() { |
197 | console.log("sug loading done"); |
198 | setTimeout(function() { |
199 | sugLoading = false; |
200 | if (sugTriggerAgain) { sugTriggerAgain = false; sugTrigger(); } |
201 | }, liveOutputDelay); |
202 | }); |
203 | } |
204 | |
205 | $(document).ready(function() { |
206 | $("textarea[name=q], input[name=q], select[name=algorithm]").on('input propertychange change', sugTrigger); |
207 | sugTrigger(); |
208 | }); |
209 | ]], +liveOutputDelay)) |
210 | + hform(p("Query (Ctrl+Enter): " |
211 | + htextarea(q, |
212 | id := "mainInput", |
213 | name := "q", |
214 | class := "auto-expand", |
215 | style := "width: 300px", |
216 | onkeydown := jquery_submitFormOnCtrlEnter(), |
217 | autofocus := dontRun || empty(q) ? true : null // autofocus for live output mode |
218 | ) + " " |
219 | /*+ hjs([[$(document).ready(function() { |
220 | autoExpandTextArea(document.getElementById("mainInput")); |
221 | });]])*/ |
222 | //+ htextfield(+q, style := "width: 300px; text-align: center", autofocus := true) |
223 | + (alg == null ? "" : alg.additionalInputs()) |
224 | + " Algorithm: " |
225 | + hselect_list(keys(algorithms), algorithm, name := "algorithm") + " " + hbutton("Go"))); |
226 | |
227 | S content = (empty(right) ? "" : div_alignRight(right)) |
228 | + div_center(centered) |
229 | + htitledSectionWithDiv("Live Result", "", |
230 | id := "liveResult", style := "display: none", |
231 | innerDivStyle := "max-height: 150px; overflow: auto") |
232 | + (output == null ? "" : h3(algorithm) + output); |
233 | |
234 | if (withFrame) { |
235 | req.framer.addInHead(hjs_handleScrollToAnchor()); |
236 | req.framer.add(content); |
237 | ret mod.completeFrame(req); |
238 | } else |
239 | ret hhtml(hhead( |
240 | hmobilefix() + hsansserif() + |
241 | loadJQuery2() + |
242 | hjs_handleScrollToAnchor() + |
243 | hjs_autoExpandingTextAreas() + |
244 | mod.webSocketHeadStuff(req) + |
245 | hNotificationPopups()) |
246 | + hbody(content)); |
247 | } |
248 | |
249 | S doAlgorithm(Map<S, IF0<Algorithm>> algorithms, S algorithm, S q, bool liveMode) { |
250 | GazelleBEA.Req req = mod.currentReq(); |
251 | StringBufferWithMaxSize out = new(1000000); // TODO: make sure HTML tags are closed properly |
252 | |
253 | IF0<Algorithm> algo = lookupPossiblyCI(algorithms, algorithm); |
254 | if (algo == null) |
255 | out.append("Algorithm not found: " + algorithm); |
256 | else { |
257 | if (isB(evalWithTimeout(algoTimeout, r { |
258 | temp mod.enter(); |
259 | temp tempSetTL(mod.currentReq, req); |
260 | Algorithm alg = algo!; |
261 | alg.liveMode = liveMode; |
262 | alg.out = out; |
263 | alg.q = q; |
264 | alg.req = mod.currentReq(); |
265 | alg.runIt(); |
266 | }))) |
267 | out.append("\n[algorithm timeout]"); |
268 | } |
269 | |
270 | ret str(out); |
271 | } |
272 | |
273 | class Algorithm implements Runnable { |
274 | S q; |
275 | GazelleBEA.Req req; |
276 | Appendable out; |
277 | //Appendable outPrio = new StringBufferWithMaxSize(10000); |
278 | bool liveMode; |
279 | Concepts localConcepts = db_mainConcepts(); //= childConcepts(db_mainConcepts()); |
280 | L<Runnable> nonMatches; // null so not filled by default |
281 | |
282 | // override for normal mode |
283 | run {} |
284 | |
285 | // override for live mode |
286 | void runLiveMode {} |
287 | |
288 | /*void cleanForStorage { |
289 | out = outPrio = null; |
290 | }*/ |
291 | |
292 | // overridable |
293 | S additionalInputs() { ret ""; } |
294 | |
295 | void appendHTML(Appendable out default this.out, S html) ctex { |
296 | if (empty(html)) ret; |
297 | html = wrapInDiv(html, style := "margin-top: 0.5em"); |
298 | out.append(html).append("\n"); |
299 | } |
300 | |
301 | void appendHTML_raw(S html) ctex { out.append(html).append("\n"); } |
302 | |
303 | void appendText(Appendable out default this.out, S text) ctex { |
304 | if (empty(text)) ret; |
305 | out.append(hpre_htmlencode(rtrim(text))); |
306 | } |
307 | |
308 | void appendTextBold(Appendable out default this.out, S text) ctex { |
309 | if (empty(text)) ret; |
310 | out.append(b(hpre_htmlencode(rtrim(text)))); |
311 | } |
312 | |
313 | void allowSuggestingAnswer(BEAObject input) { |
314 | if (input == null) ret; |
315 | S text = input.text(); |
316 | |
317 | S url = mod.baseLink + "/saveAnswer"; |
318 | appendHTML( |
319 | hpostform("Suggest an answer to " + htmlEncode_quote(text) + ": " |
320 | //+ hinputfield(+text, style := "width: 300px") |
321 | + htextarea(text, id := "suggestAnswer", name := "text", class := "auto-expand", |
322 | style := "width: 300px") |
323 | + hhidden(inputID := input.id) |
324 | + hhidden(redirect := "") |
325 | + " " + hsubmit("Save answer") |
326 | + " [Optional rewrite type: " + hinputfield("rewriteType", style := "width: 100px") + " ]", |
327 | action := url, |
328 | onsubmit := js_setRedirect())); |
329 | } |
330 | |
331 | void allowSuggestingPattern(BEAObject input) { |
332 | if (input == null) ret; |
333 | S text = input.text(); |
334 | |
335 | S url = mod.baseLink + "/savePattern"; |
336 | appendHTML( |
337 | hpostform("Suggest a pattern (with angle bracket vars): " |
338 | + htextarea(text, name := "text", class := "auto-expand", |
339 | style := "width: 300px") |
340 | + hhidden(fromInput := conceptIDOrNull(input)) |
341 | + hhidden(userTyped := true) |
342 | + hhidden(redirect := "") |
343 | + " " + hsubmit("Save pattern"), |
344 | action := url, |
345 | onsubmit := js_setRedirect())); |
346 | } |
347 | |
348 | void allowSuggestingSyntacticPattern(BEAObject input) { |
349 | if (input == null) ret; |
350 | S text = input.text(); |
351 | |
352 | S url = mod.baseLink + "/saveSyntacticPattern"; |
353 | appendHTML( |
354 | hpostform("Suggest a syntactic pattern (with * vars): " |
355 | + htextarea(text, name := "text", class := "auto-expand", |
356 | style := "width: 300px") |
357 | + hhidden(fromInput := conceptIDOrNull(input)) |
358 | + hhidden(userTyped := true) |
359 | + hhidden(redirect := "") |
360 | + " " + hsubmit("Save syntactic pattern"), |
361 | action := url, |
362 | onsubmit := js_setRedirect())); |
363 | } |
364 | |
365 | BEA saveInput(S q) { |
366 | if (userAgentIsBot(beaMod().currentUserAgent())) null; |
367 | Pair<BEA, Bool> p = uniqCI2 BEA(type := "Input", text := q); |
368 | BEA input = p.a; |
369 | mod.saveUserAgent(input); |
370 | |
371 | if (p.b) { |
372 | csetIfUnset(input, createdBy := mod.user(mod.currentReq())); |
373 | appendHTML("Input saved"); |
374 | } |
375 | ret input; |
376 | } |
377 | |
378 | void runNonMatches { |
379 | if (nempty(nonMatches)) { appendHTML(hr()); callFAll(nonMatches); } |
380 | } |
381 | |
382 | void addNonMatch(Runnable r) { add(nonMatches, r); } |
383 | |
384 | void runIt { |
385 | if (liveMode) runLiveMode(); else run(); |
386 | runNonMatches(); |
387 | } |
388 | } // end of Algorithm |
389 | |
390 | class ReverseInput extends Algorithm { |
391 | run { appendText(reversed(q)); } |
392 | void runLiveMode { run(); } |
393 | } |
394 | |
395 | class TimeoutTest extends Algorithm { |
396 | run { sleepSeconds(120); } |
397 | } |
398 | |
399 | class RunPattern extends Algorithm { |
400 | run { |
401 | BEAObject pattern = mod.beaGet(parseFirstLong(q)); |
402 | if (pattern == null) ret with appendText("Pattern not found"); |
403 | appendText("Pattern: " + pattern); |
404 | for (BEAObject input : mod.beaList("Input")) { |
405 | S text = input.text(); |
406 | SS mapping = matchInputWithPattern(input, pattern); |
407 | if (mapping == null) |
408 | addNonMatch(r { |
409 | appendText("Checking Input: " + input + " - No match"); |
410 | }); |
411 | else { |
412 | S result = "\n" + renderMappingAsText(mapping); |
413 | appendText("Checking Input: " + input + result); |
414 | allowStoringMatch(this, input, pattern, mapping); |
415 | } |
416 | } |
417 | } |
418 | } |
419 | |
420 | S renderMappingAsText(SS mapping) { |
421 | ret indent(formatDoubleArrowMap_horizontallyAligned(mapping)); |
422 | } |
423 | |
424 | class FindRewrites extends Algorithm { |
425 | run { |
426 | // argument is ID of a match |
427 | BEAObject match = mod.beaGet(parseFirstLong(q)); |
428 | if (match == null || !match.typeIs("Match")) ret with appendText("Match not found"); |
429 | BEAObject pattern = cast cget pattern(match); |
430 | BEAObject input = cast cget input(match); |
431 | SS mapping = cast get mapping(match); |
432 | appendText("Match: " + match); |
433 | appendText("Input: " + input); |
434 | appendText("Pattern: " + pattern); |
435 | appendText("Mapping:\n" |
436 | + renderMappingAsText(mapping)); |
437 | |
438 | appendRewrites(this, input, input.text(), pattern, match, mapping); |
439 | } |
440 | } |
441 | |
442 | // match and input can be null, pattern has to be set |
443 | LS appendRewrites(Algorithm algo, BEAObject input, S inputText, BEAObject pattern, BEAObject match, SS mapping) { |
444 | Cl<BEAObject> rewrites = mod.beaBackRefs(pattern, "Rewrite"); |
445 | new LS texts; |
446 | for (BEAObject r : rewrites) { |
447 | S text = r.text(); |
448 | S textWithVars = text; |
449 | if (pattern.typeIs("Syntactic pattern")) |
450 | textWithVars = starsToAngleBracketedNumbers(text); |
451 | |
452 | S text2 = replaceAngleBracketVars_curly(textWithVars, mapping); |
453 | algo.appendText(" Using pattern rewrite: " + text); |
454 | algo.appendTextBold( |
455 | " " + inputText + "\n" |
456 | + " => " + text2); |
457 | texts.add(text2); |
458 | |
459 | // look for existing rewrite |
460 | BEAObject existing = match == null || input == null ?: conceptWhereIC BEAObject( |
461 | type := "Rewrite", +input, text := text2, |
462 | +match, patternRewrite := r, label := "good" |
463 | ); |
464 | |
465 | if (existing != null) |
466 | algo.appendHTML("Rewrite exists: " + mod.beaLinkHTML(existing)); |
467 | else if (match == null) |
468 | algo.appendText("[Can't save, no match]"); |
469 | else if (input == null) |
470 | algo.appendText("[Can't save, no input object]"); |
471 | else |
472 | algo.appendHTML( |
473 | hinlinepostform( |
474 | hhiddenMulti( |
475 | action := "create", |
476 | f_type := "Rewrite", |
477 | f_text := text2, |
478 | f_input := input.id, metaInfo_input := "concept", |
479 | f_match := match.id, metaInfo_match := "concept", |
480 | f_patternRewrite := r.id, metaInfo_patternRewrite := "concept", |
481 | f_label := "good") |
482 | + hbutton("Good rewrite"), |
483 | target := "_blank", |
484 | action := mod.crudLink(BEAObject))); |
485 | } |
486 | ret texts; |
487 | } |
488 | |
489 | class ProcessNewInput extends Algorithm { |
490 | run { |
491 | BEAObject input = handleInput(this, q = trim(q), false); |
492 | |
493 | for (BEAObject pattern : mod.beaListAny("Pattern", "Syntactic Pattern")) { |
494 | checkPattern(this, input, q, pattern); |
495 | } |
496 | } |
497 | } |
498 | |
499 | void checkPattern(Algorithm algo, BEA input, S q, BEA pattern) { |
500 | SS mapping = matchInputWithPattern(q, pattern); |
501 | if (mapping == null) |
502 | algo.addNonMatch(r { |
503 | algo.appendText("Checking Pattern: " + pattern + " - No match"); |
504 | }); |
505 | else { |
506 | S result = "\n" + renderMappingAsText(mapping); |
507 | algo.appendText("Checking Pattern: " + pattern + result); |
508 | if (input == null) { |
509 | //appendHTML("Click \"Save input\" first to store this match"); |
510 | } else |
511 | allowStoringMatch(algo, input, pattern, mapping); |
512 | |
513 | appendRewrites(algo, input, q, pattern, null, mapping); |
514 | } |
515 | } |
516 | |
517 | class ProcessNewInput_v2 extends Algorithm { |
518 | run { |
519 | q = trim(q); |
520 | saveInput(q); |
521 | BEAObject input = handleInput(this, q, false); |
522 | |
523 | if (input != null) { |
524 | Cl<BEAObject> rewrites = mod.beaBackRefs(input, "Rewrite"); |
525 | BEAObject rewrite = random(rewrites); |
526 | if (rewrite != null) |
527 | appendHTML("My answer: " + b(htmlEncode2(rewrite.text())) + " " + ahref(mod.beaShortURL(rewrite), "[source]")); |
528 | } |
529 | |
530 | allowSuggestingAnswer(input); |
531 | allowSuggestingPattern(input); |
532 | allowSuggestingSyntacticPattern(input); |
533 | |
534 | for (BEAObject pattern : syntacticPatternsSortedBySpecificityDesc()) { |
535 | continue if patternAlwaysMatches(pattern); |
536 | SS mapping = matchInputWithPattern(q, pattern); |
537 | if (mapping == null) |
538 | addNonMatch(r { |
539 | appendHTML("Checking Syntactic Pattern: " + mod.beaLinkHTML(pattern) + " - No match"); |
540 | }); |
541 | else { |
542 | S result = "Grouped as: " + replaceAngleBracketVars_curly(starsToAngleBracketedNumbers(pattern.text()), mapping) + "\n" |
543 | + renderMappingAsText(mapping); |
544 | appendHTML(hr()); |
545 | appendHTML("Checking Syntactic Pattern: " + mod.beaLinkHTML(pattern)); |
546 | appendText(result); |
547 | BEAObject match = null; |
548 | if (input == null) { |
549 | //appendHTML("Click \"Save input\" first to store this match"); |
550 | } else |
551 | match = allowStoringMatch(this, input, pattern, mapping); |
552 | |
553 | MultiMap<S, BEAObject> subInputRewrites = ciMultiMap(); |
554 | |
555 | for (S subInput : uniquifyCI(values(mapping))) |
556 | if (!eqic(subInput, q)) { |
557 | BEAObject subInputObj = handleInput(this, subInput, "Sub-Input", true); |
558 | |
559 | // find rewrites for sub-input |
560 | if (subInputObj != null) { |
561 | L<BEAObject> subRewrites = concatLists( |
562 | conceptsWhereCI(BEAObject, type := "Rewrite", input := subInputObj), |
563 | conceptsWhereCI(BEAObject, type := "Rewrite", isRewriteOf := subInputObj)); |
564 | for (BEAObject r : subRewrites) |
565 | appendHTML(" Sub-Rewrite found: " + r); |
566 | subInputRewrites.putAll(subInput, subRewrites); |
567 | } |
568 | } |
569 | |
570 | // show all rewrites for the pattern |
571 | appendRewrites(this, input, q, pattern, match, mapping); |
572 | |
573 | // apply some sub-rewrites randomly |
574 | SS rewrittenMapping = mapValues(mapping, |
575 | s -> { |
576 | BEAObject rewrite = random(subInputRewrites.get(s)); |
577 | ret rewrite == null ? s : uncurly(rewrite.text()); |
578 | }); |
579 | |
580 | S randomRewrite = replaceAngleBracketVars_curly(starsToAngleBracketedNumbers(pattern.text()), rewrittenMapping); |
581 | if (neq(randomRewrite, q)) |
582 | appendText("Random rewrite from sub-inputs: " + randomRewrite); |
583 | } |
584 | } // for pattern |
585 | } |
586 | } |
587 | |
588 | class ProcessNewInput_v3 extends Algorithm { |
589 | run { |
590 | q = trim(q); |
591 | saveInput(q); |
592 | BEAObject input = handleInput(this, q, false); |
593 | |
594 | new HTMLTabs tabs; |
595 | |
596 | { |
597 | new StringBuffer toTab; |
598 | Algorithm alg = new ProcessNewInput_v2; |
599 | alg.q = q; |
600 | alg.out = toTab; |
601 | alg.runIt(); |
602 | tabs.add("Match input with patterns", toTab); |
603 | } |
604 | |
605 | { |
606 | new StringBuffer toTab; |
607 | Algorithm alg = new SyntacticPatternFromInput; |
608 | alg.q = q; |
609 | alg.out = toTab; |
610 | alg.runIt(); |
611 | tabs.add("Make syntactic pattern", toTab); |
612 | } |
613 | |
614 | appendHTML(tabs.html()); |
615 | } |
616 | } |
617 | |
618 | BEAObject allowStoringMatch(Algorithm algo, BEAObject input, BEAObject pattern, SS mapping) { |
619 | BEAObject match = conceptWhereCI(BEAObject, type := "Match", |
620 | +pattern, +input, +mapping); |
621 | if (match != null) |
622 | ret match with algo.appendHTML("Match exists: " + mod.beaLinkHTML(match)); |
623 | |
624 | /*S url = appendParamsToURL(mod.baseLink + "/storeMatch", pattern := pattern.id, input := input.id); |
625 | algo.appendHTML( |
626 | hbuttonLink(appendParamsToURL(url, label := "good"), "Good match") + " " |
627 | + hbuttonLink(appendParamsToURL(url, label := "bad"), "Bad match"));*/ |
628 | |
629 | algo.appendHTML(joinWithSpace( |
630 | storeMatchForm(input, pattern, "good"), |
631 | storeMatchForm(input, pattern, "bad"))); |
632 | |
633 | null; |
634 | } |
635 | |
636 | S storeMatchForm(BEAObject input, BEAObject pattern, S label) { |
637 | ret hinlinepostform( |
638 | hhiddenMulti( |
639 | pattern := pattern.id, |
640 | input := input.id, |
641 | +label, |
642 | redirect := "") |
643 | + hbutton(firstToUpper(label) + " match"), |
644 | action := mod.baseLink + "/storeMatch", |
645 | onsubmit := js_redirectAutoScroll2()); |
646 | } |
647 | |
648 | runnable class MakeSyntacticPatterns extends Algorithm { |
649 | for (BEAObject p : mod.beaList("Pattern")) { |
650 | appendText(p + " => " + makeSyntacticPattern(p)); |
651 | } |
652 | } |
653 | |
654 | S syntacticPatternText(BEAObject p) { |
655 | ret simpleSpacesTrim_javaTok(angleBracketVarsToStars(p.text())); |
656 | } |
657 | |
658 | // convert angle bracket var pattern to syntactic pattern |
659 | BEAObject makeSyntacticPattern(BEAObject p) { |
660 | if (p == null || !p.typeIs("Pattern") || empty(p.text())) null; |
661 | //print("makeSyntacticPattern", p); |
662 | S text = syntacticPatternText(p); |
663 | BEAObject sp = uniqCI BEAObject(type := "Syntactic Pattern", +text); |
664 | cset(p, syntacticPattern := sp); |
665 | ret sp; |
666 | } |
667 | |
668 | S processInputURL(S q) { |
669 | ret addParamsToURL(mod.baseLink + "/query", +q, algorithm := "process input"); |
670 | } |
671 | |
672 | BEAObject handleInput(Algorithm algo, S q, S desc default "Input", bool showProcessLink) { |
673 | algo.appendHTML(hSingleRowTable_withSpacing( |
674 | "\*desc*/:", |
675 | tt(htmlEncode_nlToBr_withIndents(q)), |
676 | !showProcessLink ? "" : targetBlank_noFollow(processInputURL(q), "Process"))); |
677 | |
678 | BEAObject input = mod.findInput(q); |
679 | algo.appendHTML(inputHTML(input, desc, q)); |
680 | ret input; |
681 | } |
682 | |
683 | // Link to or allow to save input object |
684 | S inputHTML(BEAObject input, S desc default "Input", S q) { |
685 | ret input != null |
686 | ? "\*desc*/ exists: " + mod.beaLinkHTML(input) |
687 | : !mod.requestAuthed() && !mod.allowAnonymousInputUpload ? null : hinlinepostform( |
688 | hhiddenMulti( |
689 | text := q, |
690 | redirect := "") |
691 | + hbutton("Save \*desc*/"), |
692 | action := mod.baseLink + "/saveInput", |
693 | onsubmit := js_setRedirect()); |
694 | } |
695 | |
696 | // Link to or allow to save syntactic pattern |
697 | S syntacticPatternLinkHTML(BEAObject obj, S text, BEAObject fromInput default null) { |
698 | S desc = "Syntactic pattern"; |
699 | ret obj != null |
700 | ? mod.beaLinkHTML(obj) |
701 | : !mod.requestAuthed() ? null : hinlinepostform( |
702 | hhiddenMulti( |
703 | +text, |
704 | fromInput := conceptIDOrNull(fromInput), |
705 | redirect := "") |
706 | + hbutton("Save \*firstToLower(desc)*/"), |
707 | action := mod.baseLink + "/saveSyntacticPattern", |
708 | onsubmit := js_setRedirect()); |
709 | } |
710 | |
711 | runnable class SyntacticPatternFromInput extends Algorithm { |
712 | //appendHTML(inputHTML(mod.findInput(q), q)); |
713 | BEAObject input = handleInput(this, q, false); |
714 | |
715 | if (countTokens(q) > 10) ret with appendText("Input too long to extract syntactic patterns"); |
716 | S q2 = dropPunctuation(q); |
717 | new L<Map> data; |
718 | for (S pat : sortedIC(gazelle_allSyntacticPatternsFromInput(q))) { |
719 | SS mapping = matchInputWithSyntacticPattern(q2, pat); |
720 | BEAObject obj = conceptWhereIC(BEAObject, type := "Syntactic Pattern", text := pat); |
721 | |
722 | /*appendHTML(htmlEncode2(pat) + " " + syntacticPatternLinkHTML(obj, pat) |
723 | + (empty(mapping) ? "" : |
724 | hpre_htmlencode(indent(formatDoubleArrowMap_horizontallyAligned(mapping)))));*/ |
725 | |
726 | Map row = litorderedmap( |
727 | "Syntactic Pattern" := htmlEncode2(pat), |
728 | "In database" := syntacticPatternLinkHTML(obj, pat, input)); |
729 | for (S key, S val : mapping) |
730 | row.put("Argument " + key, htmlEncode2(val)); |
731 | data.add(row); |
732 | } |
733 | appendHTML(htmlTable2_noHtmlEncode(data)); |
734 | } |
735 | |
736 | class ApplyTextFunctions extends Algorithm { |
737 | run { |
738 | q = trim(q); |
739 | saveInput(q); |
740 | BEAObject input = handleInput(this, q, false); |
741 | |
742 | new LinkedHashSet<BEAObject> objectsMade; |
743 | |
744 | for (BEAObject f : mod.beaList("JavaX Standard Function")) pcall { |
745 | addIfNotNull(objectsMade, reactFunctionWithInput(this, f, input)); |
746 | } |
747 | |
748 | appendHTML(h3("Results of function calls")); |
749 | |
750 | //appendHTML(ul_htmlencode(allToString(list(localConcepts, BEAObject)))); |
751 | |
752 | /*HCRUD_Concepts<BEAObject> crudData = new(localConcepts, BEAObject); |
753 | HCRUD crud = new(null, crudData); |
754 | crud.unshownFields = litset("globalID", "mirrorPost"); |
755 | |
756 | crudData.massageItemMapForList = (item, map) -> { |
757 | BEAObject o = item/BEAObject; |
758 | O value = o~.result; |
759 | map.put("result", HTML(javaValueToHTML(value, identityHashSet()))); |
760 | //map.put("Save", HTML(hbutton())); |
761 | };*/ |
762 | |
763 | HCRUD crud = mod.makeCRUD(BEAObject, mod.currentReq()); |
764 | HCRUD_Concepts crudData = cast crud.data; |
765 | crudData.listConcepts_firstStep = () -> objectsMade; |
766 | |
767 | appendHTML(crud.renderTable(true)); |
768 | } |
769 | } |
770 | |
771 | class FindPath extends Algorithm { |
772 | new BreadthFirstPathFinder_withLinkType<BEAObject, FieldIndicator> pathFinder; |
773 | BEAObject start, dest; |
774 | |
775 | run { |
776 | start = mod.beaGet(parseFirstLong(q)); |
777 | dest = mod.beaGet(parseSecondLong(q)); |
778 | if (start == null || dest == null) |
779 | ret with appendText("Please supply object IDs of start and end"); |
780 | |
781 | appendHTML("Looking for path from " + mod.beaToHTML(start) + " to " + mod.beaToHTML(dest)); |
782 | |
783 | pathFinder.getChildren = o -> cForwardAndBackRefsWithFieldIndicator BEAObject(o); |
784 | pathFinder.add(start); |
785 | |
786 | while (!pathFinder.nodeReached(dest) && pathFinder.step()) {} |
787 | |
788 | //appendHTML(hcomment(struct(pathFinder))); |
789 | LPair<BEAObject, FieldIndicator> path = pathFinder.examplePathWithTypes(start, dest); |
790 | |
791 | if (path == null) |
792 | appendText("No path found!"); |
793 | else { |
794 | appendHTML(b("Path found!")); |
795 | appendHTML(ol(map(path, p -> { |
796 | S html = mod.beaHTML(p.a); |
797 | if (p.b == null) ret html; |
798 | S arrow = ifThenElse(p.b.forward, ">>", "<<"); |
799 | ret html + " " + htmlEncode2( |
800 | joinNemptiesWithSpace(arrow, p.b.field, arrow)); |
801 | }))); |
802 | } |
803 | } |
804 | } |
805 | |
806 | class ExecuteTextQuery extends Algorithm { |
807 | run { |
808 | saveInput(q = trim(q)); |
809 | appendHTML(h3("Result")); |
810 | appendHTML(htmlEncode2(strOrEmpty(executeTextQuery(q)))); |
811 | } |
812 | } |
813 | |
814 | class InputSummary extends Algorithm { |
815 | run { |
816 | BEA mainInput = saveInput(q = trim(q)); |
817 | |
818 | Cl<BEA> inputs = conceptsWhere BEAObject(type := "Input", text := q); |
819 | if (l(inputs) > 1) |
820 | appendHTML("Note: Input appears " + l(inputs) + " times in the database: " |
821 | + joinWithSpace(map(o -> mod.beaToHTML(o), inputs))); |
822 | |
823 | for (BEA input : inputs) { |
824 | if (input != mainInput) { |
825 | appendHTML(hr()); |
826 | appendHTML("Input: " + input); |
827 | } |
828 | |
829 | // rewrites |
830 | |
831 | Cl<BEA> rewrites = mod.beaBackRefs(input, "Rewrite"); |
832 | |
833 | if (empty(rewrites)) appendHTML(h3("No rewrites")); |
834 | else |
835 | for (int i, BEA r : unpair iterateWithIndex1(rewrites)) |
836 | appendHTML("Rewrite " + i + ": " + ahref(mod.beaURL(r), tok_dropCurlyBrackets(r.text()))); |
837 | |
838 | // matches |
839 | |
840 | //beaBackRefs("Match |
841 | } |
842 | } |
843 | } |
844 | |
845 | class ApplyPatternList extends Algorithm { |
846 | S additionalInputs() { |
847 | ret hselect("patternListID", mapToKey conceptID(mod.beaList("Pattern List")), |
848 | req.get("patternListID")); |
849 | } |
850 | |
851 | run { |
852 | BEAObject input = handleInput(this, q = trim(q), false); |
853 | |
854 | BEA patternList = mod.beaGet patternListID(req); |
855 | if (patternList == null) ret; |
856 | L<BEA> patterns = cast cget patterns(patternList); |
857 | appendHTML("Pattern list: " + mod.beaHTML(patternList)); |
858 | |
859 | fOr (BEA pattern : patterns) { |
860 | appendText("Trying pattern " + pattern); |
861 | checkPattern(this, input, q, pattern); |
862 | } |
863 | } |
864 | } |
865 | |
866 | class ApplyAlgorithmObject extends Algorithm { |
867 | S additionalInputs() { |
868 | ret hselect("algorithmID", mapToKey conceptID( |
869 | concatLists( |
870 | wideningListCast Concept(list BEARegExpReplacement()), |
871 | wideningListCast Concept(conceptsWhereIC UserPost(type := "JavaX Code (HTML Bot)")) |
872 | )), |
873 | req.get("algorithmID")); |
874 | } |
875 | |
876 | void runLiveMode() { |
877 | //BEAObject input = handleInput(this, q = trim(q), false); |
878 | |
879 | Concept algo = getConcept(parseLongOpt(req.get("algorithmID"))); |
880 | //appendText("Test test. Algorithm: " + algo); |
881 | |
882 | appendHTML("Algorithm object: " + htmlEncode2_nlToBr(str(algo))); |
883 | |
884 | if (algo cast UserPost) { |
885 | //O result = algObject.apply(q); |
886 | O result = mod.callHtmlBot_dropMadeByComment(algo.id, req.params()); |
887 | appendText("Result: " + result); |
888 | } else if (algo cast BEARegExpReplacement) { |
889 | //appendHTML("Algorithm object: " + mod.beaHTML(algObject)); |
890 | O result = algo.apply(q); |
891 | appendText("Result: " + result); |
892 | } else if (algo == null) |
893 | appendText("Algorithm object not found"); |
894 | else |
895 | appendText("Unknown algorithm object type: " + _className(algo)); |
896 | } |
897 | } |
898 | |
899 | class ApplyRegExpReplacement > Algorithm { |
900 | run { |
901 | BEARegExpReplacement regExpReplacement = cast mod.beaGet(q); |
902 | if (regExpReplacement == null) ret with appendText("Please enter reg exp replacement ID"); |
903 | |
904 | appendHTML("Applying " + beaHTML(regExpReplacement)); |
905 | |
906 | for (BEA input : sortedByConceptIDDesc(mod.beaList("Input"))) { |
907 | S text = input.text(); |
908 | S replaced = regExpReplacement.apply(text); |
909 | if (neq(text, replaced)) { |
910 | appendHTML(hr()); |
911 | appendText(" " + text + "\n=> " + replaced); |
912 | appendPossibleRewrite(this, input, replaced, litmap( |
913 | f_regularExpression := regExpReplacement.id, |
914 | metaInfo_regularExpression := "concept")); |
915 | } |
916 | } |
917 | } |
918 | } |
919 | |
920 | // prints instead of rendering to page |
921 | class BackEndAlgorithm > Algorithm { |
922 | S prefix() { ret shortClassName(this) + ": "; } |
923 | @Override void appendText(S s) { printWithIndent(prefix(), s); } |
924 | @Override void appendHTML(S s) { appendText(htmlDecode_dropTags(s)); } |
925 | @Override void addNonMatch(Runnable r) { r.run(); } |
926 | } |
927 | |
928 | class MatchInputWithAllPatternLists > Algorithm { |
929 | run { |
930 | BEAObject input = saveInput(q); |
931 | |
932 | for (BEA patternList : sortedByConceptIDDesc(beaList("Pattern List"))) |
933 | reactInputWithPatternList(this, input, q, patternList, 1, 2); |
934 | } |
935 | } |
936 | |
937 | class RunTestCasesOnCodePost extends Algorithm { |
938 | S additionalInputs() { |
939 | MultiSet<S> ms = distinctCIFieldValuesOfConcepts_multiSet(BEAObject, "type"); |
940 | LS types = filter(pairsA(multiSetToPairsByPopularity(ms)), |
941 | type -> cic(type, "test case")); |
942 | |
943 | ret "Test case type: " + hselect_list("testCaseType", types, req.get("testCaseType")) |
944 | + " " + hselect("algorithmID", mapToKey conceptID( |
945 | conceptsWhereIC UserPost(type := "JavaX Code (HTML Bot)")), |
946 | req.get("algorithmID")); |
947 | } |
948 | |
949 | run { |
950 | //BEAObject input = handleInput(this, q = trim(q), false); |
951 | |
952 | S testCaseType = req.get("testCaseType"); |
953 | Concept algo = getConcept(parseLongOpt(req.get("algorithmID"))); |
954 | //appendText("Test test. Algorithm: " + algo); |
955 | |
956 | Cl<BEA> testCases = beaList(testCaseType); |
957 | |
958 | appendText(n2(testCases, "test case") + " found for type " + quote(testCaseType)); |
959 | appendHTML("Algorithm object: " + htmlEncode2_nlToBr(str(algo))); |
960 | |
961 | if (!algo instanceof UserPost) ret; |
962 | |
963 | new Scorer scorer; |
964 | |
965 | for ping (BEA testCase : testCases) { |
966 | MapSO fields = toCIMap(objectToMap(testCase)); |
967 | S input = str(getAny(fields, "input")); |
968 | S expected = str(getAny(fields, "output", "result")); |
969 | S result = str(mod.callHtmlBot_dropMadeByComment(algo.id, litmap(q := input))); |
970 | bool ok = eq(result, expected); |
971 | appendText((ok ? "OK" : "BAD") + ": Input: " + quote(input) + ", expected output: " + quote(expected) |
972 | + ", result: " + quote(result)); |
973 | scorer.add(ok); |
974 | } |
975 | |
976 | appendText(str(scorer)); |
977 | } |
978 | } |
979 | |
980 | // add algorithms here |
981 | |
982 | void reactInputWithPatternList(Algorithm algo, BEA input, S text, BEA patternList, int level, int recursionLevels) { |
983 | Pair<BEA, SS> match = matchInputWithPatternList(text, patternList); |
984 | algo.appendHTML(hr()); |
985 | algo.appendHTML(joinNemptiesWithColon( |
986 | level == 1 ? beaHTML(patternList) : null, |
987 | stringIf(match == null, "No match"))); |
988 | |
989 | if (match != null) { |
990 | BEA pattern = match.a; |
991 | SS mapping = match.b; |
992 | algo.appendHTML("Matched as " + beaHTML(pattern)); |
993 | algo.appendText(renderMappingAsText(mapping)); |
994 | |
995 | if (input != null) { |
996 | BEA matchObj = uniqCI(algo.localConcepts, BEA, |
997 | type := "Match", |
998 | +input, |
999 | +patternList, |
1000 | winningPattern := pattern, |
1001 | +mapping); |
1002 | algo.appendHTML("Match saved as: " + beaHTML(matchObj)); |
1003 | } |
1004 | |
1005 | if (level < recursionLevels) { |
1006 | algo.appendHTML_raw("<ul>"); |
1007 | for (S key, subInput : mapping) { |
1008 | if (!eqic(key, text)) { |
1009 | algo.appendHTML_raw("<li>"); |
1010 | algo.appendText("Processing sub-Input: " + subInput); |
1011 | reactInputWithPatternList(algo, null, subInput, patternList, level+1, recursionLevels); |
1012 | algo.appendHTML_raw("</li>"); |
1013 | } |
1014 | } |
1015 | algo.appendHTML_raw("</ul>"); |
1016 | } |
1017 | } |
1018 | } |
1019 | |
1020 | int patternSpecificity(BEAObject pattern) { |
1021 | ret countWordsWithoutAngleBracketedAndStars(pattern.text()); |
1022 | } |
1023 | |
1024 | L<BEAObject> syntacticPatternsSortedBySpecificityDesc() { |
1025 | ret sortedByCalculatedFieldDesc patternSpecificity(mod.beaList("Syntactic Pattern")); |
1026 | } |
1027 | |
1028 | O executeTextQuery(S s) { |
1029 | new Matches m; |
1030 | if (match3_withIntsAndIDs("all references in field <id> of object <int>", s, m)) { |
1031 | O value = cget(mod.beaGet($2), $1); |
1032 | ret value instanceof Cl ? instancesOf BEAObject((Cl) value) |
1033 | : value instanceof BEAObject ? ll((BEAObject) value) |
1034 | : ll(); |
1035 | } |
1036 | |
1037 | ret new QueryNotUnderstood(s); |
1038 | } |
1039 | |
1040 | srecord QueryNotUnderstood(S s) {} |
1041 | |
1042 | S beaToHTML(BEA o) { ret mod.beaToHTML(o); } |
1043 | S beaHTML(BEA o) { ret mod.beaHTML(o); } |
1044 | S beaURL(BEA o) { ret mod.beaURL(o); } |
1045 | |
1046 | bool isSyntacticPattern(BEA pat) { |
1047 | ret pat != null && pat.typeIs("Syntactic pattern"); |
1048 | } |
1049 | |
1050 | S patternTextWithAngleBracketVars(BEA pat) { |
1051 | S text = pat.text(); |
1052 | ret isSyntacticPattern(pat) ? starsToAngleBracketedNumbers(text) : text; |
1053 | } |
1054 | |
1055 | bool isCommentOrFeedback(BEA o) { |
1056 | ret o != null && o.typeIsOneOf("Comment", "Useful", "Feedback"); |
1057 | } |
1058 | |
1059 | S feedbackHTML(BEA o) { |
1060 | Cl<BEA> l = filter isCommentOrFeedback(mod.beaBackRefs(o)); |
1061 | ret joinWithBR(map(l, c -> c.typeIs("Comment") |
1062 | ? ahref(beaURL(c), htmlEncode2(c.text())) |
1063 | : beaHTML(c))); |
1064 | } |
1065 | |
1066 | S bestInputURL(S text) { |
1067 | text = trim(text); |
1068 | BEA input = mod.findInput(text); |
1069 | ret input != null ? beaURL(input) : processInputURL(text); |
1070 | } |
1071 | |
1072 | // also shaded |
1073 | S bestInputHTML(S text) { |
1074 | if (empty(text)) ret ""; |
1075 | ret ahref(bestInputURL(text), span(htmlEncode2(text), |
1076 | style := "background-color: #ccc")); |
1077 | } |
1078 | |
1079 | S performRewrite(BEA rewrite, SS mapping) { |
1080 | S rewriteText = starsToAngleBracketedNumbers(rewrite.text()); |
1081 | ret replaceAngleBracketVars(rewriteText, mapping); |
1082 | } |
1083 | |
1084 | PairS exampleForPatternRewrite(BEA pattern, BEA rewrite) { |
1085 | S patText = patternTextWithAngleBracketVars(pattern); |
1086 | Set<S> vars = collectAngleBracketVars(patText); |
1087 | SS mapping = mapToValues_ciMap(vars, var -> "$" + var); |
1088 | |
1089 | ret pair(replaceAngleBracketVars(patText, mapping), |
1090 | performRewrite(rewrite, mapping)); |
1091 | } |
1092 | |
1093 | /* if there is a regular expression |
1094 | * and an input |
1095 | * and the regular expression matches the input |
1096 | * generate a sub-input with the matched part |
1097 | */ |
1098 | record RegExpToPossibleSubInputs(BEA input, BEA regExp) extends Algorithm { |
1099 | run { |
1100 | S text = input.text(); |
1101 | S pat = regExp.text(); |
1102 | for (IntRange r : regexpFindRangesIC(pat, text)) |
1103 | appendHTML(beaHTML(csetAndReturn(uniq(localConcepts, BEA, |
1104 | type := "Possible Sub-Input", |
1105 | +input, |
1106 | characterRange := r, |
1107 | text := substring(text, r)), |
1108 | +regExp, |
1109 | byAlgorithm := shortName(this)))); |
1110 | } |
1111 | } |
1112 | |
1113 | void appendPossibleRewrite(Algorithm algo, BEA input, S text, Map moreInfo default null) { |
1114 | // look for existing rewrite |
1115 | BEAObject existing = input == null ?: conceptWhereIC BEAObject( |
1116 | type := "Rewrite", +input, +text, |
1117 | label := "good" |
1118 | ); |
1119 | |
1120 | if (existing != null) |
1121 | algo.appendHTML("Rewrite exists: " + mod.beaLinkHTML(existing)); |
1122 | else if (input != null) |
1123 | algo.appendHTML( |
1124 | joinWithSpace(map(ll("good", "bad"), label -> |
1125 | hinlinepostform( |
1126 | hhiddenMulti( |
1127 | action := "create", |
1128 | f_type := "Rewrite", |
1129 | f_text := text, |
1130 | f_input := input.id, metaInfo_input := "concept", |
1131 | f_label := label, |
1132 | redirectAfterSave := ""/*algo.req.uriWithParams()*/) |
1133 | + hhiddenMulti(moreInfo) |
1134 | + hbutton(firstToUpper(label) + " rewrite", |
1135 | onclick := js_redirectAutoScroll2()), |
1136 | action := mod.crudLink(BEA))))); |
1137 | } |
1138 | |
1139 | BEA reactFunctionWithInput(Algorithm algo, BEA f, BEA input) { |
1140 | S fName = getString name(f); |
1141 | if (!isIdentifier(fName)) null; |
1142 | if (!isSafeStandardFunction(fName)) |
1143 | ret null with algo?.addNonMatch(r { algo.appendText("Function " + fName + " not safe"); }); |
1144 | |
1145 | BEAObject o = cnew(algo.localConcepts, BEAObject, |
1146 | type := "Function Result", |
1147 | function := f, |
1148 | functionCalled := fName, |
1149 | +input, |
1150 | calculating := true); |
1151 | print("Function result: " + o); |
1152 | |
1153 | try { |
1154 | O holder = getStandardFunctionHolder(fName); |
1155 | O result = evalWithTimeoutOrFail(10.0, () -> call(holder, fName, input.text())); |
1156 | |
1157 | // convert string collections to list |
1158 | if (!result instanceof L && isStringCollection(result)) result = asList((Cl) result); |
1159 | |
1160 | if (result == null) |
1161 | cset(o, resultType := "null"); |
1162 | else if (result instanceof S) |
1163 | cset(o, resultType := "string", +result); |
1164 | else if (isStringList(result)) |
1165 | cset(o, resultType := "list of strings", +result); |
1166 | else |
1167 | cset(o, result := "other" + appendRoundBracketed(className(result)), |
1168 | result := shorten(1000, str(result))); |
1169 | } catch e { |
1170 | cset(o, resultType := "error", error := getStackTrace(e)); |
1171 | } |
1172 | cset(o, calculating := null); |
1173 | ret o; |
1174 | } |
1175 | |
1176 | BEA convertSyntacticToSemanticMatch(BEA match, BEA semanticPattern) { |
1177 | BEA syntacticPattern = beaGet pattern(match); |
1178 | BEA input = beaGet input(match); |
1179 | S pat2 = syntacticPattern.text(); |
1180 | S pat1 = semanticPattern.text(); |
1181 | new LS vars; |
1182 | S pat2b = angleBracketVarsToStars(pat1, vars); |
1183 | S warning = eq(pat2, pat2b) ? null |
1184 | : "Patterns don't match: " + quote(pat2) + " / " + quote(pat2b); |
1185 | SS mapping = cast cget mapping(match); |
1186 | SS mapping2 = mapKeys(mapping, key -> or(_get(vars, parseInt(key)-1), key)); |
1187 | mapping2 = putKeysFirst(vars, mapping2); // reorder variables in order of appearance in input |
1188 | BEA match2 = uniqCI BEA( |
1189 | type := "Match", |
1190 | +input, |
1191 | pattern := semanticPattern, |
1192 | fromSyntacticMatch := match); |
1193 | cset(match2, |
1194 | mapping := mapping2); |
1195 | ret match2; |
1196 | } |
1197 | |
1198 | Cl<BEA> convertSyntacticToSemanticMatches(BEA match) { |
1199 | new L<BEA> out; |
1200 | BEA syntacticPattern = beaGet pattern(match); |
1201 | for (BEA semanticPattern : mod.beaList("Pattern", +syntacticPattern)) pcall { |
1202 | out.add(convertSyntacticToSemanticMatch(match, semanticPattern)); |
1203 | } |
1204 | ret out; |
1205 | } |
1206 | |
1207 | Cl<BEA> convertSyntacticToSemanticMatchesForWholePattern(BEA pattern) { |
1208 | if (pattern.typeIs("Syntactic Pattern")) |
1209 | // This is huge - uses all semantic patterns |
1210 | ret concatMap_lists convertSyntacticToSemanticMatches(mod.beaList("Match", +pattern)); |
1211 | else { |
1212 | new L<BEA> out; |
1213 | BEA syntacticPattern = beaGet syntacticPattern(pattern); |
1214 | if (syntacticPattern != null) |
1215 | for (BEA match : mod.beaList("Match", pattern := syntacticPattern)) |
1216 | out.add(convertSyntacticToSemanticMatch(match, pattern)); |
1217 | ret out; |
1218 | } |
1219 | |
1220 | } |
1221 | |
1222 | BEA mapMethodLike beaGet(S field, BEA o) { ret mod.beaGet(field, o); } |
1223 | Cl<BEA> beaList(S type, O... params) { ret mod.beaList(type, params); } |
1224 | |
1225 | int simpleObjectScore(BEA o) { |
1226 | int score = 0; |
1227 | if (eqic_gen(o~.label, "good")) ++score; |
1228 | else if (eqic_gen(o~.label, "bad")) --score; |
1229 | Cl<BEA> l = findBackRefsWithField BEA(object := o); |
1230 | score += countWhereCI(l, type := "Useful"); |
1231 | score -= countWhereCI(l, type := "Bad"); |
1232 | ret score; |
1233 | } |
1234 | |
1235 | L<BEA> sortedBySimpleObjectScore(int minScore, Cl<BEA> l) { |
1236 | ret sortedByCalculatedFieldDesc simpleObjectScore(filter(l, o -> simpleObjectScore(o) >= minScore)); |
1237 | } |
1238 | |
1239 | BEA createPatternListFromUsefulSyntacticPatterns() { |
1240 | L<BEA> patterns = sortedBySimpleObjectScore(0, beaList("Syntactic Pattern")); |
1241 | ret mod.autoMigrateToCustomClass(uniqCI BEA(type := "Pattern List", |
1242 | byFunction := "createPatternListFromUsefulSyntacticPatterns", |
1243 | +patterns)); |
1244 | } |
1245 | |
1246 | Map<S, IF0<Algorithm>> algorithms() { |
1247 | ret litorderedmap( |
1248 | "Process new input v3" := (IF0) () -> new ProcessNewInput_v3, |
1249 | "Process new input v2" := (IF0) () -> new ProcessNewInput_v2, |
1250 | "Process new input" := (IF0) () -> new ProcessNewInput, |
1251 | "Run pattern" := (IF0) () -> new RunPattern, |
1252 | "Find rewrites for match" := (IF0) () -> new FindRewrites, |
1253 | "Reverse input (test algorithm)" := (IF0) () -> new ReverseInput, |
1254 | "Timeout test" := (IF0) () -> new TimeoutTest, |
1255 | "Syntactic pattern from input" := (IF0) () -> new SyntacticPatternFromInput, |
1256 | "Apply all text functions" := (IF0) () -> new ApplyTextFunctions, |
1257 | "Find Path" := (IF0) () -> new FindPath, |
1258 | "Execute text query" := (IF0) () -> new ExecuteTextQuery, |
1259 | "Make syntactic patterns for all patterns in DB" := (IF0) () -> new MakeSyntacticPatterns, |
1260 | "Input summary" := (IF0) () -> new InputSummary, |
1261 | "Apply pattern list" := (IF0) () -> new ApplyPatternList, |
1262 | "Apply regular expression replacement to all inputs" := (IF0) () -> new ApplyRegExpReplacement, |
1263 | "Match input with all pattern lists" := (IF0) () -> new MatchInputWithAllPatternLists, |
1264 | "Apply algorithm object" := (IF0) () -> new ApplyAlgorithmObject, |
1265 | "Run test cases on code post" := (IF0) () -> new RunTestCasesOnCodePost, |
1266 | |
1267 | // add algorithms here |
1268 | ); |
1269 | } |
1270 | |
1271 | void putAlgorithmsInDatabase { |
1272 | for (S name : keys(algorithms())) |
1273 | uniq BEA(type := "Classic Query Algorithm", +name); |
1274 | } |
1275 | |
1276 | } // end of Calculations |
download show line numbers debug dex old transpilations
Travelled to 6 computer(s): bhatertpkbcr, ekrmjmnbrukm, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
Snippet ID: | #1030833 |
Snippet name: | BEACalculations [Include] |
Eternal ID of this version: | #1030833/449 |
Text MD5: | 0af89ca0adca659c085100c1cd05d4c4 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-08-11 01:36:38 |
Source code size: | 46018 bytes / 1276 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 350 / 4035 |
Version history: | 448 change(s) |
Referenced in: | [show references] |