sclass BEACalculations { GazelleBEA mod; *(GazelleBEA *mod) {} transient int liveOutputDelay = 1000; void reactAllInputsWithSomePatterns() { for (BEAObject input : mod.beaObjectsOfType("input")) { new ReactInputWithSomePatterns r; r.input = input; r.ccOut = db_mainConcepts(); r.max = 10; r.start(); stepAllWithTimeout(10.0, r); } } class ReactInputWithSomePatterns implements Steppable { BEAObject input; Concepts ccOut; int max = 3, n; Iterator patterns; void start { n = countConceptsWhereIC(ccOut, BEAObject, +input, type := "match"); patterns = iterator(sortByConceptID(conceptsWhereIC BEAObject(type := "Pattern"))); } public bool step() { if (n >= max) false; if (!patterns.hasNext()) false; if (reactInputWithPattern(input, patterns.next(), ccOut) != null) ++n; true; } } SS matchInputWithPattern(BEAObject input, BEAObject pattern) { S text = getString text(input); ret matchInputWithPattern(text, pattern); } SS matchInputWithPattern(S text, BEAObject pattern) { S pat = getString text(pattern); if (pattern.typeIs("Syntactic Pattern")) ret matchInputWithSyntacticPattern(text, pat); else ret matchInputWithPattern(text, pat); } SS matchInputWithSyntacticPattern(S text, S pat) { pat = starsToAngleBracketedNumbers(pat); ret matchInputWithPattern(text, pat); } SS matchInputWithPattern(S text, S pat) { SS mapping = flexMatchAngleBracketVarsIC_honorPunctuation_first(pat, text); if (mapping != null) ret mapping; ret flexMatchAngleBracketVarsIC_first(pat, text); } BEAObject reactInputWithPattern(BEAObject input, BEAObject pattern, Concepts ccOut default db_mainConcepts()) { if (input == null || pattern == null) null; SS mapping = matchInputWithPattern(input, pattern); //printVars_str("reactInputWithPattern", +input, +pattern, +mapping); if (mapping == null) null; ret cnew(ccOut, BEAObject, type := "Match", +input, +pattern, +mapping); } O serveAnalyzeInput(GazelleBEA.Req req) { new Concepts ccOut; BEAObject input = getConcept BEAObject(parseLong(req.get("id"))); if (input == null) input = cnew(ccOut, BEAObject, type := "Input", text := req.get("q")); S text = getString text(input); new ReactInputWithSomePatterns r; r.input = input; r.ccOut = ccOut; r.max = 1000; r.start(); stepAllWithTimeout(10.0, r); L matches = conceptsWhereIC(ccOut, BEAObject, type := "Match"); ret h1_title("Analyze Input") + p("Input: " + b(htmlEncode(text))) + p(empty(matches) ? "No matches" : "Matches") + ul_htmlEncode(matches); } O serveQueryPage(GazelleBEA.Req req) { S q = req.get("q"), algorithm = req.get("algorithm"); bool dontRun = eq(req.get("dontRun"), "1"); bool liveOutput = eq(req.get("liveOutput"), "1"); if (liveOutput) ret jsonEncode(answer := "Live output demo: " + htmlEncode2(q)); Map> algorithms = litorderedmap( "Process new input v2" := (IF0) () -> new ProcessNewInput2, "Process new input" := (IF0) () -> new ProcessNewInput, "Run pattern" := (IF0) () -> new RunPattern, "Find rewrites for match" := (IF0) () -> new FindRewrites, "Reverse input (test algorithm)" := (IF0) () -> new ReverseInput, "Timeout test" := (IF0) () -> new TimeoutTest, "Make syntactic patterns" := (IF0) () -> new MakeSyntacticPatterns, "Syntactic pattern from input" := (IF0) () -> new SyntacticPatternFromInput, // add algorithms here ); S output = empty(algorithm) || dontRun ? null : doAlgorithm(algorithms, algorithm, q); S right = mod.html_loggedIn(); S centered = htitle_h2(ahref(mod.baseLink + "/", "Gazelle BEA") + " Query") + hscript(replaceVars([[ var sugLoading = false, sugTriggerAgain = false; function sugTrigger() { console.log("sugTrigger"); if (sugLoading) { sugTriggerAgain = true; return; } // get form data as JSON var data = {"liveOutput" : "1", "q": "test", "algorithm": "Reverse input (test algorithm)"}; const url = "/query"; console.log("Loading " + url); sugLoading = true; $.post(url, data, function(result) { console.log("Suggestor result: " + result); const answer = !result ? "" : JSON.parse(result).answer; if (answer) { $("#suggestorResult .sectionContents").html(answer); $("#suggestorResult").show(); } else $("#suggestorResult").hide(); //$("#suggestorResult").html(answer ? "Suggestor says: " + answer : ""); } ).always(function() { console.log("sug loading done"); setTimeout(function() { sugLoading = false; if (sugTriggerAgain) { sugTriggerAgain = false; sugTrigger(); } }, liveOutputDelay); }); } $(document).ready(function() { $("input[name=q], select[name=algorithm]").on('input propertychange change', sugTrigger); sugTrigger(); }); ]], +liveOutputDelay)) + hform(p("Query: " + htextfield(+q, style := "width: 300px; text-align: center", autofocus := true, oninput := "sugTrigger();") + "   Algorithm: " + hselect_list(keys(algorithms), algorithm, name := "algorithm") + "   " + hbutton("Go")); ret hmobilefix() + hsansserif() + loadJQuery2() + div_alignRight(right) + div_center(centered) + (output == null ? "" : h3(algorithm) + output); } S doAlgorithm(Map> algorithms, S algorithm, S q) { GazelleBEA.Req req = mod.currentReq!; StringBufferWithMaxSize out = new(1000000); IF0 algo = lookupPossiblyCI(algorithms, algorithm); if (algo == null) out.append("Algorithm not found: " + algorithm); else { if (isB(evalWithTimeout(10.0, r { temp tempSetTL(mod.currentReq, req); Algorithm alg = algo!; alg.q = q; alg.out = out; alg.run(); }))) out.append("\n[algorithm timeout]"); } ret str(out); } abstract sclass Algorithm implements Runnable { S q; Appendable out; Appendable outPrio = new StringBufferWithMaxSize(10000); void appendHTML(Appendable out default this.out, S html) ctex { if (empty(html)) ret; html = wrapInDiv(html, style := "margin-top: 0.5em"); out.append(html).append("\n"); } void appendText(Appendable out default this.out, S text) ctex { if (empty(text)) ret; out.append(hpre_htmlencode(rtrim(text))); } void appendTextBold(Appendable out default this.out, S text) ctex { if (empty(text)) ret; out.append(b(hpre_htmlencode(rtrim(text)))); } } runnable class ReverseInput extends Algorithm { appendText(reversed(q)); } class TimeoutTest extends Algorithm { run { sleepSeconds(120); } } class RunPattern extends Algorithm { new L nonMatches; run { BEAObject pattern = mod.beaGet(parseFirstLong(q)); if (pattern == null) ret with appendText("Pattern not found"); appendText("Pattern: " + pattern); for (BEAObject input : mod.beaList("Input")) { S text = input.text(); SS mapping = matchInputWithPattern(input, pattern); if (mapping == null) nonMatches.add(r { appendText("Checking Input: " + input + " - No match"); }); else { S result = "\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping)); appendText("Checking Input: " + input + result); allowStoringMatch(this, input, pattern, mapping); } } callFAll(nonMatches); } } class FindRewrites extends Algorithm { run { // argument is ID of a match BEAObject match = mod.beaGet(parseFirstLong(q)); if (match == null || !match.typeIs("Match")) ret with appendText("Match not found"); BEAObject pattern = cast cget pattern(match); BEAObject input = cast cget input(match); SS mapping = cast get mapping(match); appendText("Match: " + match); appendText("Input: " + input); appendText("Pattern: " + pattern); appendText("Mapping:\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping))); appendRewrites(this, input, input.text(), pattern, match, mapping); } } // match and input can be null, pattern has to be set LS appendRewrites(Algorithm algo, BEAObject input, S inputText, BEAObject pattern, BEAObject match, SS mapping) { Cl rewrites = mod.beaBackRefs(pattern, "Rewrite"); new LS texts; for (BEAObject r : rewrites) { S text = r.text(); S text2 = replaceAngleBracketVars_curly(text, mapping); algo.appendText(" Using pattern rewrite: " + text); algo.appendTextBold( " " + inputText + "\n" + " => " + text2); texts.add(text2); // look for existing rewrite BEAObject existing = match == null || input == null ?: conceptWhereIC BEAObject( type := "Rewrite", +input, text := text2, +match, patternRewrite := r, label := "good" ); if (existing != null) algo.appendHTML("Rewrite exists: " + mod.beaLinkHTML(existing)); else if (match != null && input != null) algo.appendHTML( hinlinepostform( hhiddenMulti( action := "create", f_type := "Rewrite", f_text := text2, f_input := input.id, metaInfo_input := "concept", f_match := match.id, metaInfo_match := "concept", f_patternRewrite := r.id, metaInfo_patternRewrite := "concept", f_label := "good") + hbutton("Good rewrite"), target := "_blank", action := mod.crudLink(BEAObject))); } ret texts; } class ProcessNewInput extends Algorithm { new L nonMatches; run { q = trim(q); BEAObject input = handleInput(this, q, false); for (BEAObject pattern : mod.beaListAny("Pattern", "Syntactic Pattern")) { SS mapping = matchInputWithPattern(q, pattern); if (mapping == null) nonMatches.add(r { appendText("Checking Pattern: " + pattern + " - No match"); }); else { S result = "\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping)); appendText("Checking Pattern: " + pattern + result); if (input == null) { //appendHTML("Click \"Save input\" first to store this match"); } else allowStoringMatch(this, input, pattern, mapping); appendRewrites(this, input, q, pattern, null, mapping); } } callFAll(nonMatches); } } class ProcessNewInput2 extends Algorithm { new L nonMatches; run { q = trim(q); if (uniqCI_trueIfNew BEAObject(type := "Input", text := q, createdBy := mod.user(mod.currentReq!))) appendHTML("Input saved"); BEAObject input = handleInput(this, q, false); for (BEAObject pattern : mod.beaList("Syntactic Pattern")) { SS mapping = matchInputWithPattern(q, pattern); if (mapping == null) nonMatches.add(r { appendHTML("Checking Syntactic Pattern: " + mod.beaLinkHTML(pattern) + " - No match"); }); else { S result = "Grouped as: " + replaceAngleBracketVars_curly(starsToAngleBracketedNumbers(pattern.text()), mapping) + "\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping)); appendHTML(hr()); appendHTML("Checking Syntactic Pattern: " + mod.beaLinkHTML(pattern)); appendText(result); BEAObject match = null; if (input == null) { //appendHTML("Click \"Save input\" first to store this match"); } else match = allowStoringMatch(this, input, pattern, mapping); MultiMap subInputRewrites = ciMultiMap(); for (S subInput : uniquifyCI(values(mapping))) if (!eqic(subInput, q)) { BEAObject subInputObj = handleInput(this, subInput, "Sub-Input", true); // find rewrites for sub-input if (subInputObj != null) { L subRewrites = concatLists( conceptsWhereCI(BEAObject, type := "Rewrite", input := subInputObj), conceptsWhereCI(BEAObject, type := "Rewrite", isRewriteOf := subInputObj)); for (BEAObject r : subRewrites) appendHTML("  Sub-Rewrite found: " + r); subInputRewrites.putAll(subInput, subRewrites); } } // show all rewrites for the pattern appendRewrites(this, input, q, pattern, match, mapping); // apply some sub-rewrites randomly SS rewrittenMapping = mapValues(mapping, s -> { BEAObject rewrite = random(subInputRewrites.get(s)); ret rewrite == null ? s : uncurly(rewrite.text()); }); S randomRewrite = replaceAngleBracketVars_curly(starsToAngleBracketedNumbers(pattern.text()), rewrittenMapping); if (neq(randomRewrite, q)) appendText("Random rewrite from sub-inputs: " + randomRewrite); } } // for pattern if (nempty(nonMatches)) { appendHTML(hr()); callFAll(nonMatches); } } } BEAObject allowStoringMatch(Algorithm algo, BEAObject input, BEAObject pattern, SS mapping) { BEAObject match = conceptWhereCI(BEAObject, type := "Match", +pattern, +input, +mapping); if (match != null) ret match with algo.appendHTML("Match exists: " + mod.beaLinkHTML(match)); S url = appendParamsToURL(mod.baseLink + "/storeMatch", pattern := pattern.id, input := input.id); algo.appendHTML( hbuttonLink(appendParamsToURL(url, label := "good"), "Good match") + " " + hbuttonLink(appendParamsToURL(url, label := "bad"), "Bad match")); null; } runnable class MakeSyntacticPatterns extends Algorithm { for (BEAObject p : mod.beaList("Pattern")) { appendText(p + " => " + makeSyntacticPattern(p)); } } S syntacticPatternText(BEAObject p) { ret simpleSpacesTrim_javaTok(angleBracketVarsToStars(p.text())); } // convert angle bracket var pattern to syntactic pattern BEAObject makeSyntacticPattern(BEAObject p) { if (p == null || !p.typeIs("Pattern") || empty(p.text())) null; print("makeSyntacticPattern", p); S text = syntacticPatternText(p); BEAObject sp = uniqCI BEAObject(type := "Syntactic Pattern", +text); cset(p, syntacticPattern := sp); ret sp; } BEAObject handleInput(Algorithm algo, S q, S desc default "Input", bool showProcessLink) { algo.appendHTML("\*desc*/: " + tt(htmlEncode(q)) + (!showProcessLink ? "" : " " + targetBlank(addParamsToURL(mod.baseLink + "/query", +q, algorithm := "Process new input v2"), "Process"))); BEAObject input = mod.findInput(q); algo.appendHTML(inputHTML(input, desc, q)); ret input; } // Link to or allow to save input object S inputHTML(BEAObject input, S desc default "Input", S q) { ret input != null ? "\*desc*/ exists: " + mod.beaLinkHTML(input) : !mod.requestAuthed() && !mod.allowAnonymousInputUpload ? null : hinlinepostform( hhiddenMulti( text := q, redirect := "") + hbutton("Save \*desc*/"), action := mod.baseLink + "/saveInput", onsubmit := js_setRedirect()); } // Link to or allow to save syntactic pattern S syntacticPatternLinkHTML(BEAObject obj, S text) { S desc = "Syntactic pattern"; ret obj != null ? mod.beaLinkHTML(obj) : !mod.requestAuthed() ? null : hinlinepostform( hhiddenMulti( +text, redirect := "") + hbutton("Save \*firstToLower(desc)*/"), action := mod.baseLink + "/saveSyntacticPattern", onsubmit := js_setRedirect()); } runnable class SyntacticPatternFromInput extends Algorithm { //appendHTML(inputHTML(mod.findInput(q), q)); handleInput(this, q, false); if (countTokens(q) > 7) ret with appendText("Input too long to extract syntactic patterns"); S q2 = dropPunctuation(q); new L data; for (S pat : gazelle_allSyntacticPatternsFromInput(q)) { SS mapping = matchInputWithSyntacticPattern(q2, pat); BEAObject obj = conceptWhereIC(BEAObject, type := "Syntactic Pattern", text := pat); /*appendHTML(htmlEncode2(pat) + " " + syntacticPatternLinkHTML(obj, pat) + (empty(mapping) ? "" : hpre_htmlencode(indent(formatDoubleArrowMap_horizontallyAligned(mapping)))));*/ Map row = litorderedmap( "Syntactic Pattern" := htmlEncode2(pat), "In database" := syntacticPatternLinkHTML(obj, pat)); for (S key, S val : mapping) row.put("Argument " + key, htmlEncode2(val)); data.add(row); } appendHTML(print(htmlTable2_noHtmlEncode(data))); } // add algorithms here } // end of Calculations