!7 static new L data; concept Para { S text; L split; bool ok; } p { db(); parasFromText(); makeData(); serveHttpOpenBrowser(4000); } static synchronized NanoHTTPD.Response serve(S uri, NanoHTTPD.Method method, Map header, Map parms, Map files) { if (neq(uri, "/")) ret serve404(); if (nempty(parms.get("update"))) { Set toCheck = asSet(map(f toLong, keysDeprefixNemptyValue(parms, "ok_"))); //print("toCheck: " + struct(toCheck)); for (Para p) cset(p, ok := toCheck.contains(p.id)); makeData(); } if (nempty(parms.get("resplit"))) resplit(); S title = "Splitting paragraphs into sentences"; ret serveHTML(hhtml( hhead(htitle(title) + loadJQuery() + hCheckBoxMultiSelect()) + hbody(h3(title) + hformPOST(p(hhidden("resplit", "1") + hsubmit("Resplit"))) + hformPOST( hhidden("update", "1") + p(hsubmit()) + htable_noEncode(data) + p(hsubmit()))))); } svoid parasFromText { S text = loadSnippet(#1008407); for (S line : toLinesFullTrim(text)) { if (line.startsWith("#")) continue; uniq(Para, text := line); } } svoid makeData { data.clear(); for (Para p) { if (p.split == null) { p.split = splitIntoSentences_v3(p.text); p.change(); } S sp; if (l(p.split) == 1 && eq(first(p.split), p.text)) sp = "-"; else //sp = htmlEncode_nlToBr(lines(p.split)); sp = ul(htmlEncodeAll(p.split)); data.add(litorderedmap( "Original Paragraph" := htmlencode(p.text), "Split" := sp, "OK" := hcheckbox("ok_" + p.id, p.ok, "class" := "chkbox"))); } data = sortByCalculatedField(data, func(Map m) { comparableList( contains(getString(m, "OK"), "checked"), neq(m.get("Split"), "-"), m.get("Original Paragraph")) }); } svoid resplit { for (Para p) { L split = splitIntoSentences_v3(p.text); if (neq(split, p.split)) { p.split = split; p.ok = false; p.change(); } } makeData(); }