Warning : session_start(): open(/var/lib/php/sessions/sess_lg4d8i5ug4hfft92r9sgtufqla, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning : session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
// See #1023660 for the older 99 lines version
import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.text.*;
import java.util.TimeZone;
class main {
static class PhysicalSlice extends Concept {
Ref slicePage = new Ref(); // page that describes this slice
}
static class Page extends Concept {
static String _fieldOrder = "slice globalID url q";
Ref slice = new Ref(); // where are we stored
String globalID = aGlobalID();
String url, q;
}
static class Entry extends Concept {
static String _fieldOrder = "globalID page count key value ip signer";
String globalID = aGlobalID();
Ref page = new Ref();
int count;
String key, value;
String ip;
Ref signer = new Ref();
}
static class Signer extends Concept {
static String _fieldOrder = "globalID publicKey trusted approvedBy";
String globalID = aGlobalID();
String publicKey;
boolean trusted = false;
String approvedBy;
}
static class Session extends Concept {
String cookie;
Page slicePage;
}
static Map searchTypeToText = litmap(
"leven" , "Leven",
"literal" , "Literal",
"scored" , "Scored");
static int displayLength = 140;
static int sideDisplayLength = 50; // when in side bar
static int searchResultsToShow = 50;
static String sideSearchType = "literal";
static int lines;
static boolean asyncSearch = false;
static boolean allowMultipleCasesInValues = true;
static boolean showSliceSelector = false;
static ConceptFieldIndexDesc idx_latestEntries, idx_latestCreatedPages, idx_latestChangedPages;
public static void main(final String[] args) throws Exception {
dbIndexingCI(Page.class, "url", Page.class, "q", Entry.class, "key", Entry.class, "value");
dbIndexing(Signer.class, "publicKey");
dbIndexing(Session.class, "cookie");
// legacy conversions!
//for (Page p) cset(p, q := p.url);
moveSlicelessPagesToTheWildSlice();
idx_latestCreatedPages = new ConceptFieldIndexDesc(Page.class, "created");
idx_latestChangedPages = new ConceptFieldIndexDesc(Page.class, "_modified");
idx_latestEntries = new ConceptFieldIndexDesc(Entry.class, "created");
// Approve this machine's key
PKIKeyPair machineKey = agiBot_trustedKeyForMachine();
if (machineKey != null) {
print("Approving this machine's key: " + machineKey.publicKey);
cset(uniq_sync(Signer.class, "publicKey" , machineKey.publicKey), "trusted" , true, "approvedBy" , "local");
}
lines = countLines(mySource());
}
// DB functions
static boolean hasPage(String q) { return hasConceptWhereIC(Page.class, "q", q); }
static String getValue(Page page, String key) {
return page == null || empty(key) ? null : getString("value",highestByField("count",objectsWhereIC(findBackRefs(page, Entry.class), "key", key)));
}
static String getValue(String page, String key) {
return getValue(findPageFromQ(page), key);
}
static String pageDisplayName(Page page) {
/*S name = getValue(page, "read as");
bool unnaturalName = nempty(name) && !eq(makeAGIDomain(name), page.url);
ret unnaturalName ? name + " " + squareBracketed(page.url) : or2(name, unpackAGIDomainOpt(page.url));*/
return page.q;
}
// Serve page
static Object html(String uri, final Map params) { try {
return new Request().serve(uri, params);
} catch (Exception __e) { throw rethrow(__e); } }
static class Request {
String cookie;
Session session;
String uri;
Map params;
// should also work for standalone
boolean isHomeDomain() {
String domain = domain();
return eqic(domain, "www.agi.blue") || !ewic(domain, ".agi.blue");
}
Object serve(String uri, Map params) {
this.uri = uri;
this.params = params;
Matches m = new Matches();
print(uri + " ? " + unnull(subBot_query()));
cookie = cookieFromUser();
if (cookie != null)
session = uniq_sync(Session.class, "cookie", cookie);
else
session = unlistedWithValues(Session.class);
// Check for special URIs
if (swic(uri, "/bot/")) return serveBot();
// eleu appends a slash to the URI if it's a single identifier, so we drop it again
String uri2 = dropTrailingSlash(uri);
if (eqic(uri2, "/search")) return serveScoredSearch();
if (eqic(uri2, "/literalSearch")) return serveLiteralSearch();
if (eqic(uri2, "/levenSearch")) return serveLevenSearch();
if (eqic(uri2, "/query")) return serveQueryPage();
String selectSlice = params.get("slice");
if (nempty(selectSlice))
cset(session, "slicePage" , pageFromQ(selectSlice));
String q = params.get("q");
String domain = or2(params.get("domain"), domain());
String raw = firstKeyWithValue("", params); // agi.blue?something
if (nempty(raw) && empty(q)) q = raw;
/*if (nempty(q)) {
domain = makeAGIDomain(q);
if (l(domain) > maximumDomainPartLength()) // escape with "domain="
ret hrefresh(agiBlueURL() + hquery(+domain, key := "read as", value := q));
ret hrefresh("http://" + domain + (eq(q, domain) ? "" : "/" + hquery(key := "read as", value := q)));
//uri = "/"; replaceMapWithParams(params, key := "read as", value := q);
}*/
String url = domain + dropTrailingSlash(uri);
// domain to query
//if (empty(q)) q = url;
if (empty(q)) q = agiBlue_urlToQuery(url);
Page page; boolean newPage = false; Pair __1= uniqCI2_sync(Page.class, "q", q); page = __1.a; newPage = __1.b;
if (newPage) dbLog("New page", "q", q);
//printStructs(+params, +raw, +q);
String top = hcomment("cookie: " + takeFirst(4, session.cookie))
+ hSilentComputatorWithFlag("agi.blue: " + q)
+ p(ahref(agiBlueURL(), hsnippetimg("#1101682", "width" , 565/5, "height" , 800/5, "title" , "Robot by Peerro @ DeviantArt")))
+ p(small(
b(ahref(agiBlueURL(), htmlEncode2(agiBlueName())))
+ (agiBlue_isOriginal() ? "" : " " + targetBlank("http://agi.blue", "[original]"))
+ " | " + targetBlank(progLink(), "source code") + " of this web site (" + nLines(lines) + ") | " + targetBlank("https://gitter.im/agi-blue/community", "sponsor https?") + " | by " + targetBlank("https://BotCompany.de", "BC") + " | " + targetBlank("http://fiverr.tinybrain.de/", "Fiverr") + " | " + targetBlank("https://discordapp.com/invite/SEAjPqk", "Discord") + " | " + targetBlank("https://www.youtube.com/watch?v=b6jtRdV3Ev8", "Video")
+ " | " + targetBlank("http://code.botcompany.de/1024233", "Notes")
+ " | " + ahref("/query", "Query")
));
if (empty(params.get("q")) && empty(raw) && isHomeDomain()) {
List pages = sortedByFieldDesc("_modified",list(Page.class)); // TODO: use index
int start = parseInt(params.get("start")), step = 100;
String nav = pageNav2("/", l(pages), start, step, "start");
return hhtml2(hhead_title("agi.blue Overview") // SERVE HOME PAGE
+ hbody(hfullcenterAndTopLeft(top
+ hform(b("GIVE ME INPUT:") + " " + htextinput("q", "autofocus" , true) + " " + hsubmit("Ask"))
+ h1(htmlEncode2(agiBlueName()) + " has " + nPages(countConcepts(Page.class)) + " and " + nEntries(countConcepts(Entry.class)))
+ p(nav)
+ p_nemptyLines(map(pageToHTMLLink(), subList(pages, start, start+step))),
!showSliceSelector ? "" : hform("Select reality slice: " + hselect_list(availableSlices(), getString("q",session.slicePage), "name" , "slice") + " " + hsubmit("Go"))
)));
}
String key = trim(params.get("key")), value = trim(params.get("value"));
List entries = new GetEntriesAndPost().go(page, params).entries;
Set get = asCISet(nempties(subBot_paramsAsMultiMap().get("get")));
//S get = params.get('get);
if (nempty(get))
return serveJSON(collect("value",llNotNulls(firstThat(entries, e -> get.contains(e.key)))));
String key2 = key, value2 = value; if (nempty(key) && nempty(value)) key2 = value2 = ""; // input reset
boolean withHidden = eq(params.get("withHidden"), "1");
Set hide = new HashSet();
if (!withHidden) for (Entry e : entries) if (eqic(e.key, "hide") && isSquareBracketedInt(e.value)) addAll(hide, e.count, parseInt(unSquareBracket(e.value)));
MultiMap mmMeta = new MultiMap();
for (Entry e : entries) if (isSquareBracketedInt(e.key)) mmMeta.put(parseInt(unSquareBracket(e.key)), e.value);
MultiMap mm = new MultiMap();
for (Entry e : entries) mm.put(e.key, e.value);
//S name = or2(/* ouch */ last(mm.get("read as")), /* end ouch */ unpackAGIDomain(page.url), page.url);
String name = page.q;
// Find references
List refs = concatLists(conceptsWhereIC(Entry.class,"value" , name),
conceptsWhereIC(Entry.class,"key" , name));
Set refPages = asSet(ccollect("page",refs));
refPages.remove(page); // don't list current page as reference
// Search in page names (depending on default search type)
List searchResults;
if (eq(sideSearchType, "leven"))
searchResults = levenSearch(page.q, "max" , 50);
else if (eq(sideSearchType, "literal"))
searchResults = literalSearch(page.q, "max" , 50);
else
searchResults = (List) dm_call("agiBlueSearch", "search", page.q, "maxResult" , searchResultsToShow+1, "agiBlueBotID" , programID());
searchResults.remove(page);
String mainContents =
top + h1(ahref_unstyled("http://" + url + hquery("q", q), htmlEncode2(shorten(displayLength, name))) + (newPage ? " [huh????]" : ""))
+ p_nemptyLines(map(entries, new F1() { String get(Entry e) { try {
return !withHidden && (hide.contains(e.count) || eqic(e.key, "read as") && eqic(e.value, name)) ? ""
: "[" + e.count + "] " +
renderThing(e.key, false) + ": " +
b(renderThing(e.value, cic(mmMeta.get(e.count), "is a URL")));
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "!withHidden && (hide.contains(e.count) || eqic(e.key, \"read as\") && eqic(e.va..."; }}))
+ hpostform(h3("Add an entry")
+ "Key: " + hinputfield("key" , key2) + " Value: " + hinputfield("value" , value2) + " " + hsubmit("Add")
)
+ p(ahref(agiBlueURL() + "/literalSearch" + hquery("q" , page.q), "[literal search]", "title" , "Search pages with a name containing this page's name literally")
+ " " +
ahref(agiBlueURL() + "/levenSearch" + hquery("q" , page.q), "[leven search 1]", "title" , "Search pages with a Levenshtein similarity of 1 containing this page's name literally")
+ " " +
ahref(agiBlueURL() + "/search" + hquery("q" , page.q), "[scored search]", "title" , "Search pages with ScoredSearch"));
String sideContents =
hform(b("GIVE ME INPUT:") + " "
+ htextinput("q") + " "
+ hsubmit("Ask", "onclick" , "document.getElementById('newInputForm').target = '';") + " "
+ hsubmit("+Tab", "title" , "Ask and show result in a new tab", "onclick" , "document.getElementById('newInputForm').target = '_blank';"),
"id" , "newInputForm")
+ h3("References (" + l(refPages) + ")")
+ p_nemptyLines_showFirst(10, map(pageToHTMLLink("displayLength" , sideDisplayLength), refPages))
+ h3(searchTypeToText.get(sideSearchType) + " search results (" + (l(searchResults) >= searchResultsToShow ? searchResultsToShow + "+" : str(l(searchResults))) + ")")
+ p_nemptyLines_showFirst(searchResultsToShow, map(pageToHTMLLink("displayLength" , sideDisplayLength), searchResults))
+ hdiv("", "id" , "extraStuff");
// TODO: sync search delivery with WebSocket creation
if (asyncSearch)
doLater(6.0, new Runnable() { public void run() { try { dm_call("agiBlueSearch", "searchAndPost", page.q, "agiBlueBotID" , programID()) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "dm_call(\"agiBlueSearch\", \"searchAndPost\", page.q, agiBlueBotID := programID())"; }});
// serve a concept page
return hhtml2(hhead_title(pageDisplayName(page)) + hbody(
tag("table", tr(
td(mainContents, "align" , "center", "valign" , "top") +
td(sideContents, "align" , "right", "valign" , "top")),
"width" , "100%", "height" , "100%")));
}
Object servePagesToBot(Iterable pages) {
return serveListToBot(map(pageToMap(wrapMapAsParams(params)), pages));
}
Object serveListToBot(Collection l) {
if (nempty(params.get("max")))
l = takeFirst(parseInt(params.get("max")), l);
return serveJSON(l);
}
// uri starts with "/bot/"
Object serveBot() {
String q = params.get("q");
if (eqic(uri, "/bot/hello")) return serveJSON("hello");
if (eqic(uri, "/bot/hasPage")) return serveJSON(hasPage(q));
if (eqic(uri, "/bot/randomPageContaining")) {
assertNempty(q);
return servePageToBot(random(filter(list(Page.class), p -> cic(p.q, q))), params);
}
if (eqic(uri, "/bot/allPages"))
return servePagesToBot(list(Page.class));
if (eqic(uri, "/bot/allPagesStartingWith")) {
assertNempty(q);
return servePagesToBot(filter(list(Page.class), p -> swic(p.q, q)));
}
if (eqic(uri, "/bot/allPagesEndingWith")) {
assertNempty(q);
return servePagesToBot(filter(list(Page.class), p -> ewic(p.q, q)));
}
if (eqic(uri, "/bot/allPagesContaining")) {
assertNempty(q);
return servePagesToBot(filter(list(Page.class), p -> cic(p.q, q)));
}
if (eqic(uri, "/bot/allPagesContainingRegexp")) {
assertNempty(q);
Pattern pat = regexpIC(q);
return servePagesToBot(filter(list(Page.class), p -> regexpFindIC(pat, p.q)));
}
if (eqicOneOf(uri, "/bot/postSigned", "/bot/makePhysicalSlice", "/bot/approveTrustRequest")) {
String text = rtrim(params.get("text"));
String key = getSignerKey(text);
if (empty(key)) return subBot_serve500("Please include your public key");
if (!isSignedWithKey(text, key)) return subBot_serve500("Signature didn't verify");
text = dropLastTwoLines(text); // drop signer + sig line
Signer signer = uniq_sync(Signer.class,"publicKey" , key);
if (eqic(uri, "/bot/makePhysicalSlice")) {
if (!signer.trusted) return subBot_serve500("Untrusted signer");
Page page = findPageFromParams(jsonDecodeMap(text));
if (page == null) return subBot_serve500("Page not found");
return serveJSON(uniq2_sync(PhysicalSlice.class, "slicePage" , page).b ? "Slice made" : "Slice exists");
}
if (eqic(uri, "/bot/postSigned")) {
List out = new ArrayList();
for (String line : tlft(text)) {
Map map = jsonDecodeMap(line);
GetEntriesAndPost x = new GetEntriesAndPost();
x.signer = signer;
Page page = findOrMakePageFromParams(map);
if (page == null) { out.add("Invalid page reference"); continue; }
x.go(page, map);
out.add(x.newEntry ? "Saved" : x.entry != null ? "Entry exists" : "Need key and value");
}
return serveJSON(out);
}
if (eqic(uri, "/bot/approveTrustRequest")) {
if (!signer.trusted) return subBot_serve500("Untrusted signer");
Signer toApprove = conceptWhere(Signer.class,"publicKey" , trim(text));
if (toApprove == null) return subBot_serve500("Signer to approve not found");
cset(toApprove, "trusted" , true, "approvedBy" , signer.globalID);
return serveJSON("Approved: " + trim(text));
}
return subBot_serve500("CONFUSION");
}
if (eqic(uri, "/bot/post")) {
GetEntriesAndPost x = new GetEntriesAndPost();
x.go(pageFromQ(q), params);
return serveJSON(x.newEntry ? "Saved" : x.entry != null ? "Entry exists" : "Need key and value");
}
if (eqic(uri, "/bot/entriesOnPage"))
return serveJSON(map(entriesOnPage(findPageFromParams(params)), entryToMap(false)));
if (eqic(uri, "/bot/lookup")) {
String key = params.get("key");
if (empty(key)) return serveJSON("Need key");
String value = getValue(findPageFromParams(params), key);
return serveJSON(empty(value) ? "" : litmap("value", value));
}
if (eqic(uri, "/bot/latestEntries"))
return serveJSON(map(takeFirst(10, idx_latestEntries.objectIterator()), entryToMap(true)));
if (eqic(uri, "/bot/latestPages"))
return serveJSON(map(takeFirst(10, idx_latestCreatedPages.objectIterator()), pageToMap()));
if (eqic(uri, "/bot/latestChangedPages"))
return serveJSON(map(takeFirst(10, idx_latestChangedPages.objectIterator()), pageToMap()));
if (eqic(uri, "/bot/totalPageCount"))
return serveJSON(countConcepts(Page.class));
if (eqic(uri, "/bot/pageWithoutPhysicalSliceCount"))
return serveJSON(countConceptsWhere(Page.class, "slice" , null));
if (eqic(uri, "/bot/physicalSliceCount"))
return serveJSON(countConcepts(PhysicalSlice.class));
if (eqic(uri, "/bot/trustedSignersCount"))
return serveJSON(countConcepts(Signer.class, "trusted" , true));
if (eqic(uri, "/bot/valueSearch")) {
String value = params.get("value");
List entries = conceptsWhereIC(Entry.class,"value", value);
return serveJSON(map(takeFirst(100, entries), entryToMap(true)));
}
if (eqic(uri, "/bot/keyAndValueSearch")) {
String key = params.get("key"), value = params.get("value");
Collection pages = pagesForKeyAndValue(key, value);
return servePagesToBot(pages);
}
if (eqic(uri, "/bot/keyValuePairsByPopularity")) {
List> pairs = map(list(Entry.class), e -> pair(e.key, e.value));
List> pairs2 = multiSetTopPairs(ciMultiSet(map("pairToUglyStringForCIComparison",pairs)));
return serveJSON(map(pairs2, p -> {
String key; String value ; Pair __2= pairFromUglyString(p.a); key = __2.a; value = __2.b;
return litorderedmap("n" , p.b, "key", key, "value", value);
}));
}
if (eqic(uri, "/bot/allKeys"))
return serveListToBot(distinctCIFieldValuesOfConcepts(Entry.class,"key"));
if (eqic(uri, "/bot/allKeysByPopularity"))
return serveListToBot(mapMultiSetByPopularity(distinctCIFieldValuesOfConcepts_multiSet(Entry.class,"key"), (key, n) -> litorderedmap("n", n, "key", key)));
if (eqic(uri, "/bot/dbSize"))
return serveJSON(l(conceptsFile()));
if (eqic(uri, "/bot/query")) {
String query = params.get("query");
List lines = agiBlue_parseQueryScript(query);
Map vars = ciMap();
for (ALQLLine line : lines) {
if (line instanceof ALQLReturn)
return serveJSON(ll(getOrKeep(vars, ((ALQLReturn) line).var)));
else if (line instanceof ALQLTriple) {
T3 t = ((ALQLTriple) line).triple;
t = tripleMap(t, s -> getOrKeep(vars, s));
Collection pages;
String var;
if (isDollarVar(t.c)) {
var = t.c;
if (isDollarVar(t.a)) {
if (isDollarVar(t.b)) throw todo(t);
Entry e = random(conceptsWhereCI(Entry.class,"key" , t.b));
if (e == null) return serveJSON("No results for " + var);
pages = pagesForKeyAndValue(t.b, t.c);
vars.put(t.a, e.page.get().q);
vars.put(t.c, e.value);
continue;
} else if (isDollarVar(t.b)) {
Page page = findPageFromQ(t.a);
Entry e = random(findBackRefs(page, Entry.class));
if (e == null) return serveJSON("No results for " + var);
vars.put(t.b, e.key);
vars.put(t.c, e.value);
continue;
} else {
String val = getValue(t.a, t.b);
if (val == null) return serveJSON("No results for " + var);
pages = ll(pageFromQ(val));
}
} else if (isDollarVar(t.b)) {
var = t.b;
if (isDollarVar(t.c)) throw todo(t);
if (isDollarVar(t.a)) {
List entries = conceptsWhereCI(Entry.class,"value" , t.c);
if (empty(entries)) return serveJSON("No results for " + var);
Entry e = random(entries);
vars.put(t.a, e.page.get().q);
vars.put(t.b, e.key);
continue;
} else {
Collection keys = keysForPageAndValue(t.a, t.c);
if (empty(keys)) return serveJSON("No results for " + var);
pages = map("pageFromQ",keys);
}
} else {
var = t.a;
if (!isDollarVar(t.a)) throw todo(t);
if (isDollarVar(t.b)) throw todo(t);
if (isDollarVar(t.c)) throw todo(t);
pages = pagesForKeyAndValue(t.b, t.c);
}
if (empty(pages)) return serveJSON("No results for " + var);
vars.put(var, random(pages).q);
} else
throw fail("Can't interpret: " + line);
}
return serveJSON("No return statement");
}
// end of serveBot()
return subBot_serve404();
}
Object serveLiteralSearch() {
String q = params.get("q");
List searchResults = literalSearch(q);
return serveSearchResults("literal search" , q, searchResultsToShow, searchResults);
}
List literalSearch(String q, Object... __) {
int searchResultsToShow = optPar("max",__, 100);
// quick search in random order
//L searchResults = takeFirst(searchResultsToShow+1, filterIterator(iterator(list(Page)), p -> cic(p.q, q));
// full search, order by length
return takeFirst(searchResultsToShow+1, pagesSortedByLength(filter(list(Page.class), p -> cic(p.q, q))));
}
Object serveScoredSearch() {
String q = params.get("q");
List searchResults = (List) dm_call("agiBlueSearch", "search", q);
return serveSearchResults("scored search" , q, searchResultsToShow, searchResults);
}
Object serveLevenSearch() {
String q = params.get("q");
List searchResults = levenSearch(q);
return serveSearchResults("leven search with distance 1" , q, searchResultsToShow, searchResults);
}
List levenSearch(String q, Object... __) {
int searchResultsToShow = optPar("max",__, 100);
int maxEditDistance = 1;
Map map = new HashMap();
for (Page p : list(Page.class)) {
int distance = leven_limitedIC(q, p.q, maxEditDistance+1);
if (distance <= maxEditDistance) map.put(p, distance);
}
return takeFirst(searchResultsToShow+1, keysSortedByValue(map));
}
Object serveSearchResults(String searchType, String q, int searchResultsToShow, Collection searchResults) {
String title = "agi.blue " + searchType + " for " + htmlEncode2(quote(q)) + " (" + (l(searchResults) >= searchResultsToShow ? searchResultsToShow + "+ results" : nResults(l(searchResults))) + ")";
return hhtml2(hhead_title(htmldecode_dropAllTags(title))
+ hbody(hfullcenter(//top +
h3(title)
+ p_nemptyLines_showFirst(searchResultsToShow, map(pageToHTMLLink(), searchResults)))));
}
Object serveQueryPage() {
String query = params.get("query");
if (query == null) query = loadSnippet("#1024258");
String title = ahref("/", "agi.blue") + " | Execute a query script (" + targetBlank("http://code.botcompany.de/1024274", "ALQL") + ")";
return hhtml2(hhead_title(htmldecode_dropAllTags(title))
+ hbody(hfullcenter(
h3(title)
+ form(
htextarea(query, "name" , "query", "cols" , 80, "rows" , 10, "autofocus" , true)
+ " "
+ hsubmit("Execute"), "action" , "/bot/query")
)));
}
} // end of class Request
static void dbLog(Object... params) {
logStructure(programFile("db.log"), ll(params));
}
static IF1 pageToMap(Object... __) {
boolean withEntries = boolPar("withEntries",__);
boolean nameOnly = eqOneOf(optPar("nameOnly",__), "1", true);
if (nameOnly) return (IF1) p -> litmap("q" , p.q);
return (IF1) p -> {
List entries = findBackRefs(p, Entry.class);
return litorderedmap(
"q" , p.q,
"nEntries" , l(entries),
"created" , p.created,
"modified" , p._modified,
"entries" , !withEntries ? null : map(entries, entryToMap(false)));
};
}
static IF1 entryToMap(boolean withPage) {
return (IF1) e -> litorderedmap(
"created" , e.created,
"i" , e.count,
"key" , e.key,
"value" , e.value,
"q" , withPage ? e.page.get().q : null,
"signer" , getString("globalID",e.signer.get()));
}
static Object servePageToBot(Page page, Map params) {
if (page == null) return serveJSON(null);
params = asCIMap(params);
Map map = pageToMap("withEntries" , valueIs1("withEntries",params)).get(page);
return serveJSON(map);
}
static class GetEntriesAndPost {
List entries;
Entry entry;
boolean newEntry = false;
Signer signer;
GetEntriesAndPost go(Page page, Map params) {
String key = trim(params.get("key")), value = trim(params.get("value"));
print("GetEntriesAndPost: " + quote(page.q) + ", " + quote(key) + " := " + quote(value));
{ withDBLock(new Runnable() { public void run() { try {
entries = findBackRefs(page, Entry.class);
if (nempty(key) && nempty(value)) {
String ip = subBot_clientIP();
entry = firstThat(e -> eqic(e.key, key) && eq_icIf(!allowMultipleCasesInValues, e.value, value) && eq(e.ip, ip), entries);
if (entry == null) {
print("SAVING");
Entry e = cnew(Entry.class,"page", page, "key", key, "value", value, "ip", ip, "count" , l(entries) + 1, "signer", signer);
page.change(); // bump modification date
entry = e;
newEntry = true;
entries.add(entry);
dbLog("New entry", "page" , page.q, "globalID" , e.globalID, "count" , e.count, "key", key, "value", value);
}
}
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "entries = findBackRefs(page, Entry);\r\n if (nempty(key) && nempty(value))..."; }}); }
sortByFieldInPlace("created",entries);
numberEntriesInConceptField("count",entries);
return this;
}
}
static Page findPageFromParams(Map map) {
String q = getString("q",map);
return empty(q) ? null : findPageFromQ(q);
}
static Page findOrMakePageFromParams(Map map) {
return pageFromQ(getString("q",map));
}
static Page findPageFromQ(String q) {
return conceptWhereCI(Page.class,"q", q);
}
static Page pageFromQ(String q) {
return empty(q) ? null : uniqCI_sync(Page.class,"q", q);
}
static F1 pageToHTMLLink(Object... __) {
int displayLength = optPar("displayLength",__, main.displayLength);
return new F1() { String get(Page p) { try {
String name = pageDisplayName(p);
return ahref(agiBlueURL() + hquery("q" , p.q),
htmlEncode2(shorten(displayLength, name)),
"title" , name);
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "S name = pageDisplayName(p);\r\n ret ahref(agiBlueURL() + hquery(q := p.q),\r..."; }};
}
static Collection backSearch(String key, String value) {
// we query the index for the value field because that yields fewer results
return map(conceptsWhereCI(Entry.class,"value" , "a slice of reality", "key" , "is"), e -> e.page.get().q);
}
static Collection availableSlices() {
return moveElementToBeginningIC("the default slice", backSearch("is", "a slice of reality"));
//ret ll("the default slice", "the everything slice", "the robot slice");
}
static PhysicalSlice getOrMakePhysicalSlice(Page p) {
PhysicalSlice slice = first(findBackRefs(PhysicalSlice.class,p));
if (slice == null)
slice = uniq_sync(PhysicalSlice.class, "slicePage" , p);
return slice;
}
static PhysicalSlice theWildSlice() {
return getOrMakePhysicalSlice(pageFromQ("the wild slice"));
}
static void moveSlicelessPagesToTheWildSlice() {
PhysicalSlice slice = theWildSlice();
for (Page p : conceptsWhere(Page.class,"slice" , null)) {
print("Moving to wild slice: " + p.q);
cset_sync(p, "slice", slice);
}
}
static String renderThing(String s, boolean forceURLDisplay) {
return forceURLDisplay || isURL(s) || isAGIDomain(s)
? ahref(fixAGILink(absoluteURL(s)), htmlencode2(shorten(displayLength, s)))
: ahref(agiBlue_linkForPhrase(s), htmlencode2(shorten(displayLength, s)));
}
static List entriesOnPage(Page p) {
return p == null ? null : sortedByField("count",findBackRefs(p, Entry.class));
}
static List pagesSortedByLength(List l) {
return sortedByCalculatedField(l, p -> l(p.q));
}
static String hhtml2(String contents) {
return hhtml(hAddToHead_fast(contents,
hIncludeGoogleFont("Source Sans Pro")
+ hmobilefix()
+ hstylesheet("body { font-family: Source Sans Pro }")));
}
static Set pagesForKeyAndValue(String key, String value) {
List entries = conceptsWhereIC(Entry.class,"value", value, "key", key);
return asSet(ccollect("page",entries));
}
static Collection keysForPageAndValue(String q, String value) {
Page page = findPageFromQ(q);
if (page == null) return null;
return collect("key",conceptsWhereIC(Entry.class,"page", page, "value", value));
}
static boolean agiBlue_isOriginal() {
return amProgram("#1023558");
}
static String agiBlueURL() {
return agiBlue_isOriginal() ? "http://agi.blue" : myLink("");
}
static String agiBlueName() {
return agiBlue_isOriginal() ? "agi.blue" : "agi.blue clone " + programID();
}
static String pairToUglyStringForCIComparison(Pair p) {
return p == null ? null : l(p.a) + "|" + p.a + "|" + p.b;
}
static String aGlobalID() {
return randomID(globalIDLength());
}
static HashMap litmap(Object... x) {
HashMap map = new HashMap();
litmap_impl(map, x);
return map;
}
static void litmap_impl(Map map, Object... x) {
if (x != null) for (int i = 0; i < x.length-1; i += 2)
if (x[i+1] != null)
map.put(x[i], x[i+1]);
}
static void dbIndexingCI(Object... params) {
db();
for (int i = 0; i < l(params); i += 2)
indexConceptFieldCI((Class) params[i], (String) params[i+1]);
}
static void dbIndexing(Object... params) {
db();
for (int i = 0; i < l(params); i += 2)
indexConceptField((Class) params[i], (String) params[i+1]);
}
static PKIKeyPair agiBot_trustedKeyForMachine() {
return pkiKeyPairFromTwoLineFile(agiBot_trustedKeyForMachine_file());
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal print_byThread; // special handling by thread - prefers F1
static volatile Object print_allThreads;
static volatile Object print_preprocess;
static void print() {
print("");
}
static A print(String s, A o) {
print((endsWithLetterOrDigit(s) ? s + ": " : s) + o);
return o;
}
// slightly overblown signature to return original object...
static A print(A o) {
ping_okInCleanUp();
if (print_silent) return o;
String s = String.valueOf(o) + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
Object f = getThreadLocal(print_byThread_dontCreate());
if (f == null) f = print_allThreads;
if (f != null)
// We do need the general callF machinery here as print_byThread is sometimes shared between modules
if (isFalse(
f instanceof F1 ? ((F1) f).get(s) :
callF(f, s))) return;
print_raw(s);
}
static void print_raw(String s) {
if (print_preprocess != null) s = (String) callF(print_preprocess, s);
s = fixNewLines(s);
Appendable loc = local_log;
Appendable buf = print_log;
int loc_max = print_log_max;
if (buf != loc && buf != null) {
print_append(buf, s, print_log_max);
loc_max = local_log_max;
}
if (loc != null)
print_append(loc, s, loc_max);
System.out.print(s);
}
static void print_autoRotate() {
}
// returns number of changes
static int cset(Concept c, Object... values) { try {
if (c == null) return 0;
int changes = 0;
values = expandParams(c.getClass(), values);
warnIfOddCount(values);
for (int i = 0; i+1 < l(values); i += 2) {
String field = (String) values[i];
Object value = values[i+1];
Field f = setOpt_findField(c.getClass(), field);
//print("cset: " + c.id + " " + field + " " + struct(value) + " " + f);
if (value instanceof RC) value = c._concepts.getConcept((RC) value);
value = deref(value);
if (value instanceof String && l((String) value) >= concepts_internStringsLongerThan) value = intern((String) value);
if (f == null) {
// TODO: keep ref if it exists
mapPut2(c.fieldValues, assertIdentifier(field), value instanceof Concept ? c.new Ref((Concept) value) : value);
c.change();
} else if (isSubtypeOf(f.getType(), Concept.Ref.class)) {
((Concept.Ref) f.get(c)).set((Concept) derefRef(value));
c.change(); ++changes;
} else {
Object old = f.get(c);
if (neq(value, old)) {
f.set(c, value);
if ((f.getModifiers() & java.lang.reflect.Modifier.TRANSIENT) == 0) c.change();
++changes;
}
}
}
return changes;
} catch (Exception __e) { throw rethrow(__e); } }
static A uniq_sync(final Class c, final Object... params) {
return withDBLock(new F0 () { A get() { try { return uniq(c, params); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ret uniq(c, params);"; }});
}
static int countLines(String s) {
return l(toLines(s)); // yeah could be optimized :-)
}
static String mySource() {
return loadSnippet(programID());
}
static boolean hasConceptWhereIC(Class extends Concept> c, Object... params) {
return conceptWhereIC(c, params) != null;
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
if (o instanceof byte[]) return empty((byte[]) o);
if (o == null) return true;
throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); }
static boolean empty(File f) { return getFileSize(f) == 0; }
static String getString(Map map, Object key) {
return map == null ? null : (String) map.get(key);
}
static String getString(List l, int idx) {
return (String) get(l, idx);
}
static String getString(Object o, Object key) {
if (o instanceof Map) return getString((Map) o, key);
if (key instanceof String)
return (String) getOpt(o, (String) key);
throw fail("Not a string key: " + getClassName(key));
}
static String getString(String key, Object o) {
return getString(o, (Object) key);
}
static A highestByField(String field, Collection l) {
A best = null;
Object bestValue = null;
if (l != null) for(A a : l) {
Object val = getOpt(a, field);
if (val != null && (bestValue == null || cmp(val, bestValue) > 0)) {
best = a;
bestValue = val;
}
}
return best;
}
static A highestByField(Collection l, String field) {
return highestByField(field, l);
}
static int count(Collection l, Object o) {
int count = 0;
for (Object x : l)
if (eq(x, o))
++count;
return count;
}
static List objectsWhereIC(Collection c, Object... data) {
if (c == null) return null;
List l = new ArrayList();
for (A x : c)
if (checkFieldsIC(x, data))
l.add(x);
return l;
}
static List findBackRefs(Collection extends Concept> concepts, Class type) {
IdentityHashMap l = new IdentityHashMap();
for (Concept c : concepts)
if (c.backRefs != null) for (Concept.Ref r : c.backRefs)
if (instanceOf(r.concept(), type))
l.put((A) r.concept(), true);
return asList(keys(l));
}
// TODO: sort by ID?
static List findBackRefs(Concept c, Class type) {
IdentityHashMap l = new IdentityHashMap();
if (c != null && c.backRefs != null) for (Concept.Ref r : c.backRefs)
if (instanceOf(r.concept(), type))
l.put((A) r.concept(), true);
return asList(keys(l));
}
static List findBackRefs(Class type, Concept c) {
return findBackRefs(c, type);
}
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static String domain() {
return domainName();
}
static boolean eqic(String a, String b) {
if ((a == null) != (b == null)) return false;
if (a == null) return true;
return a.equalsIgnoreCase(b);
}
static boolean eqic(char a, char b) {
if (a == b) return true;
char u1 = Character.toUpperCase(a);
char u2 = Character.toUpperCase(b);
if (u1 == u2) return true;
return Character.toLowerCase(u1) == Character.toLowerCase(u2);
}
static boolean ewic(String a, String b) {
return endsWithIgnoreCase(a, b);
}
static boolean ewic(String a, String b, Matches m) {
return endsWithIgnoreCase(a, b, m);
}
static String unnull(String s) {
return s == null ? "" : s;
}
static Collection unnull(Collection l) {
return l == null ? emptyList() : l;
}
static List unnull(List l) {
return l == null ? emptyList() : l;
}
static Map unnull(Map l) {
return l == null ? emptyMap() : l;
}
static Iterable unnull(Iterable i) {
return i == null ? emptyList() : i;
}
static A[] unnull(A[] a) {
return a == null ? (A[]) new Object[0] : a;
}
static BitSet unnull(BitSet b) {
return b == null ? new BitSet() : b;
}
//ifclass Symbol
static Pair unnull(Pair p) {
return p != null ? p : new Pair(null, null);
}
static String subBot_query() {
return (String) mapGet(subBot_getHttpFiles(), "query");
}
static String cookieFromUser() {
return (String) callOpt(getBot("#1002157"), "cookieFromUser");
}
// make concept instance that is not connected to DB & set fields
static A unlistedWithValues(Class c, Object... params) {
A a = unlisted(c);
cset(a, params);
return a;
}
static boolean swic(String a, String b) {
return startsWithIgnoreCase(a, b);
}
static boolean swic(String a, String b, Matches m) {
if (!swic(a, b)) return false;
m.m = new String[] {substring(a, l(b))};
return true;
}
static String dropTrailingSlash(String s) {
return dropSuffix("/", s);
}
static boolean nempty(Collection c) {
return !empty(c);
}
static boolean nempty(CharSequence s) {
return !empty(s);
}
static boolean nempty(Object[] o) { return !empty(o); }
static boolean nempty(byte[] o) { return !empty(o); }
static boolean nempty(int[] o) { return !empty(o); }
static boolean nempty(Map m) {
return !empty(m);
}
static boolean nempty(Iterator i) {
return i != null && i.hasNext();
}
static boolean nempty(Object o) { return !empty(o); }
static String or2(String a, String b) {
return nempty(a) ? a : b;
}
static String or2(String a, String b, String c) {
return or2(or2(a, b), c);
}
static A firstKeyWithValue(Map map, B value) {
if (map != null) for (Map.Entry e : map.entrySet())
if (eq(e.getValue(), value))
return e.getKey();
return null;
}
static A firstKeyWithValue(B value, Map map) {
return firstKeyWithValue(map, value);
}
static String agiBlue_urlToQuery(String url) {
String s = unpackAGIDomainOpt(url);
if (s != null && neqic(s, "www")) return s.replace("-", " ");
return url;
}
static Pair uniqCI2_sync(final Class c, final Object... params) {
return withDBLock(new F0>() { Pair get() { try { return uniqCI2(c, params); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ret uniqCI2(c, params);"; }});
}
static String hcomment(String text) {
return "";
}
static List takeFirst(List l, int n) {
return l(l) <= n ? l : newSubListOrSame(l, 0, n);
}
static List takeFirst(int n, List l) {
return takeFirst(l, n);
}
static String takeFirst(int n, String s) { return substring(s, 0, n); }
static String takeFirst(String s, int n) { return substring(s, 0, n); }
static List takeFirst(int n, Iterable i) {
List l = new ArrayList();
Iterator it = i.iterator();
for (int _repeat_429 = 0; _repeat_429 < n; _repeat_429++) { if (it.hasNext()) l.add(it.next()); else break; }
return l;
}
static String hSilentComputatorWithFlag(String flag) {
return hSilentComputator(hSilentComputator_defaultURI(), flag);
}
static String p(Object contents, Object... params) {
return tag("p", contents, params) + "\n";
}
static String ahref(String link, Object contents, Object... params) {
return link == null ? str(contents) : href(link, contents, params);
}
static String hsnippetimg(String imageID, Object... params) {
return himg(snippetImageLink(imageID), params);
}
static String small(Object contents, Object... params) {
return tag("small", contents, params);
}
static String b(Object contents, Object... params) {
return tag("b", contents, params);
}
static String htmlEncode2(String s) {
return htmlencode_noQuotes(s);
}
static String targetBlank(String link, Object contents, Object... params) {
return hrefBlank(link, contents, params);
}
static String progLink(String id) {
return "http://tinybrain.de/" + parseSnippetID(id);
}
static String progLink() {
return progLink(programID());
}
static String nLines(int n) { return n2(n, "line"); }
static String nLines(Collection l) { return nLines(l(l)); }
static List sortedByFieldDesc(Collection c, String field) {
List l = new ArrayList(c);
sort(l, descFieldComparator(field));
return l;
}
static List sortedByFieldDesc(String field, Collection c) {
return sortedByFieldDesc(c, field);
}
static List list(Class type) {
return db_mainConcepts().list(type);
}
static List list(Concepts concepts, Class type) {
return concepts.list(type);
}
static List list(String type) {
return db_mainConcepts().list(type);
}
static List list(Concepts concepts, String type) {
return concepts.list(type);
}
static int parseInt(String s) {
return empty(s) ? 0 : Integer.parseInt(s);
}
static int parseInt(char c) {
return Integer.parseInt(str(c));
}
// step = e.g. 100
// value = 0 to count
static String pageNav2(String baseLink, int count, int value, int step, String nVar, Object... __) {
List l = new ArrayList();
baseLink += contains(baseLink, "?") ? "&" : "?"
+ urlencode(nVar) + "=";
if (value > 0) l.add(ahref(baseLink + max(0, value-step),
stringPar("leftArrow",__, htmlencode(unicode_leftPointingTriangle()))));
for (int i = 0; i < count; i += step) {
int n = i/step+1;
if (pageNav2_showPage(value, i, step, count))
if (value == i)
l.add(b(n));
else
l.add(ahref(baseLink + i, n));
}
if (value+step < count) l.add(ahref(baseLink + (value+step),
stringPar("rightArrow",__, htmlencode(unicode_rightPointingTriangle()))));
return p("Pages: " + lines(l));
}
static boolean pageNav2_showPage(int actual, int i, int step, int count) {
int diff = abs(actual-i)/step;
return i == 0 || i >= (count-1)/step*step || diff <= 10 || ((i/step) % 10) == 9;
}
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(Object o) {
return o == null ? 0
: o instanceof String ? l((String) o)
: o instanceof Map ? l((Map) o)
: o instanceof Collection ? l((Collection) o)
: o instanceof Object[] ? l((Object[]) o)
: o instanceof boolean[] ? l((boolean[]) o)
: o instanceof byte[] ? l((byte[]) o)
: o instanceof char[] ? l((char[]) o)
: o instanceof short[] ? l((short[]) o)
: o instanceof int[] ? l((int[]) o)
: o instanceof float[] ? l((float[]) o)
: o instanceof double[] ? l((double[]) o)
: o instanceof long[] ? l((long[]) o)
: (Integer) call(o, "size");
}
static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); }
static String hhead_title(String title) {
return hhead(htitle(title));
}
static String hbody(Object contents, Object... params) {
return tag("body", contents, params);
}
static String hfullcenterAndTopLeft(Object contents, Object topLeft) {
return tag("table",
tr(td(topLeft, "align" , "left", "height" , "1")) +
tr(td(contents, "align" , "center")),
"width" , "100%", "height" , "100%");
}
static String hform(Object contents, Object... params) {
return htag("form", contents, params);
}
// first element of params can be the value
static String htextinput(String name, Object... params) {
Object value = "";
if (odd(l(params))) {
value = params[0];
params = dropFirst(params);
}
params = html_massageAutofocusParam(params);
return tag("input", "",
concatArrays(new Object[] {"type", "text", "name", name, "value", value}, params));
}
static String htextinput(String name) {
return htextinput(name, "");
}
static String hsubmit(String text, Object... params) {
return tag("input", "", concatArrays(new Object[] {"type", "submit", "value", text}, params));
}
static String hsubmit() {
return hsubmit("Submit");
}
static String h1(String s, Object... params) {
return tag("h1", s, params);
}
static String nPages(int n) { return n2(n, "page"); }
static String nPages(Collection l) { return nPages(l(l)); }
static int countConcepts(Concepts concepts, Class c, Object... params) {
return concepts.countConcepts(c, params);
}
static int countConcepts(Class c, Object... params) {
return db_mainConcepts().countConcepts(c, params);
}
static int countConcepts() {
return db_mainConcepts().countConcepts();
}
static int countConcepts(String className) {
return db_mainConcepts().countConcepts(className);
}
static int countConcepts(Concepts concepts, String className) {
return concepts.countConcepts(className);
}
static int countConcepts(Concepts concepts) {
return concepts.countConcepts();
}
static String nEntries(int n) { return n2(n, "entry", "entries"); }
static String nEntries(Collection l) { return nEntries(l(l)); }
static String p_nemptyLines(Iterable l) {
return p(nlToBr(nemptyLines(l)));
}
static List map(Iterable l, Object f) { return map(f, l); }
static List map(Object f, Iterable l) {
List x = emptyList(l);
if (l != null) for (Object o : l)
x.add(callF(f, o));
return x;
}
static List map(Iterable l, F1 f) { return map(f, l); }
static List map(F1 f, Iterable l) {
List x = emptyList(l);
if (l != null) for (A o : l)
x.add(callF(f, o));
return x;
}
static List map(IF1 f, Iterable l) { return map(l, f); }
static List map(Iterable l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
x.add(f.get(o));
return x;
}
static List map(IF1 f, A[] l) { return map(l, f); }
static List map(A[] l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
x.add(f.get(o));
return x;
}
static List map(Object f, Object[] l) { return map(f, asList(l)); }
static List map(Object[] l, Object f) { return map(f, l); }
static List map(Object f, Map map) {
return map(map, f);
}
// map: func(key, value) -> list element
static List map(Map map, Object f) {
List x = new ArrayList();
if (map != null) for (Object _e : map.entrySet()) {
Map.Entry e = (Map.Entry) _e;
x.add(callF(f, e.getKey(), e.getValue()));
}
return x;
}
static List subList(List l, int startIndex) {
return subList(l, startIndex, l(l));
}
static List subList(List l, int startIndex, int endIndex) {
if (l == null) return null;
int n = l(l);
startIndex = Math.max(0, startIndex);
endIndex = Math.min(n, endIndex);
if (startIndex >= endIndex) return ll();
if (startIndex == 0 && endIndex == n) return l;
return l.subList(startIndex, endIndex);
}
static String hselect_list(Collection entries, Object... params) {
StringBuilder buf = new StringBuilder();
String selected = null;
if (odd(l(params))) {
selected = str(first(params));
params = dropFirst(params);
}
int i = indexOf(params, "allowEmpty");
if (even(i)) {
buf.append(" \n");
params[i] = params[i+1] = null;
}
if (nempty(entries)) for (String k : entries) {
String value = k;
buf.append(tag("option", htmlencode(str(or(value, ""))),
"value" , k,
"selected" , eq(selected, k) ? "selected" : null)).append("\n");
}
return tag("select", buf, params) + "\n";
}
static String trim(String s) { return s == null ? null : s.trim(); }
static String trim(StringBuilder buf) { return buf.toString().trim(); }
static String trim(StringBuffer buf) { return buf.toString().trim(); }
static TreeSet asCISet(Iterable c) {
return toCaseInsensitiveSet(c);
}
static TreeSet asCISet(String... x) {
return toCaseInsensitiveSet(x);
}
static List nempties(Collection c) {
return filterNempty(c);
}
static MultiMap subBot_paramsAsMultiMap() {
return decodeHQueryToMultiMap(mapGet(subBot_getHttpFiles(), "query"));
}
static Object serveJSON(Object data) {
return serveJSON_shallowLineBreaks(data);
}
static List collect(Collection c, String field) {
return collectField(c, field);
}
static List collect(String field, Collection c) {
return collectField(c, field);
}
/*ifclass Concept
static L collect(Class c, S field) {
ret collect(list(c), field);
}
endif
TODO: make translator ignore stuff in ifclass until resolved
*/
static List llNotNulls(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) if (x != null) l.add(x);
return l;
}
static A firstThat(Iterable l, Object pred) {
if (l != null) for (A a : l)
if (checkCondition(pred, a))
return a;
return null;
}
static A firstThat(Iterable l, IF1 pred) {
return firstThat(l, (Object) pred);
}
static A firstThat(IF1 pred, Iterable l) {
return firstThat(l, pred);
}
static boolean eq(Object a, Object b) {
return a == null ? b == null : a == b || b != null && a.equals(b);
}
static boolean isSquareBracketedInt(String s) {
return isSquareBracketed(s) && isInteger(deSquareBracket(s));
}
static void addAll(Collection c, Iterable b) {
if (c != null && b != null) for (A a : b) c.add(a);
}
static boolean addAll(Collection c, Collection b) {
return c != null && b != null && c.addAll(b);
}
static boolean addAll(Collection c, B... b) {
return c != null && c.addAll(Arrays.asList(b));
}
static Map addAll(Map a, Map extends A,? extends B> b) {
if (a != null) a.putAll(b);
return a;
}
static String unSquareBracket(String s) {
return deSquareBracket(s);
}
static List concatLists(Collection ... lists) {
List l = new ArrayList();
if (lists != null) for (Collection list : lists)
if (list != null)
l.addAll(list);
return l;
}
static List concatLists(Collection extends Collection > lists) {
List l = new ArrayList();
if (lists != null) for (Collection list : lists)
if (list != null)
l.addAll(list);
return l;
}
static List conceptsWhereIC(Class c, Object... params) {
return conceptsWhereIC(db_mainConcepts(), c, params);
}
static List conceptsWhereIC(String c, Object... params) {
return conceptsWhereIC(db_mainConcepts(), c, params);
}
static List conceptsWhereIC(Concepts concepts, Class c, Object... params) {
params = expandParams(c, params);
return filterConceptsIC(concepts.list(c), params);
}
static List conceptsWhereIC(Concepts concepts, String c, Object... params) {
return filterConceptsIC(concepts.list(c), params);
}
static Set asSet(Object[] array) {
HashSet set = new HashSet();
for (Object o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(String[] array) {
TreeSet set = new TreeSet();
for (String o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(Iterable l) {
if (l instanceof Set) return (Set) l;
HashSet set = new HashSet();
for (A o : unnull(l))
if (o != null)
set.add(o);
return set;
}
static List ccollect(Collection extends Concept> c, String field) {
List l = new ArrayList();
if (c != null) for (Concept a : c)
l.add(cget(a, field));
return l;
}
static List ccollect(String field, Collection extends Concept> c) {
return ccollect(c, field);
}
static Object dm_call(Object moduleOrID, String method, Object... args) {
Object mod = dm_getModule(moduleOrID);
if (mod == null) return null;
AutoCloseable __525 = dm_enter(mod); try {
return call_withVarargs(mod, method, args);
} finally { _close(__525); }}
static String programID() {
return getProgramID();
}
static String programID(Object o) {
return getProgramID(o);
}
static String ahref_unstyled(String link, Object contents, Object... params) {
return link == null ? str(contents) : ahref(link, contents,
paramsPlus(params, "style" , "text-decoration: none; color: inherit"));
}
static String hquery(Map params) {
return htmlQuery(params);
}
static String hquery(Object... data) {
return htmlQuery(data);
}
static int shorten_default = 100;
static String shorten(String s) { return shorten(s, shorten_default); }
static String shorten(String s, int max) {
return shorten(s, max, "...");
}
static String shorten(String s, int max, String shortener) {
if (s == null) return "";
if (max < 0) return s;
return s.length() <= max ? s : substring(s, 0, min(s.length(), max-l(shortener))) + shortener;
}
static String shorten(int max, String s) { return shorten(s, max); }
static boolean cic(Collection l, String s) {
return containsIgnoreCase(l, s);
}
static boolean cic(String[] l, String s) {
return containsIgnoreCase(l, s);
}
static boolean cic(String s, char c) {
return containsIgnoreCase(s, c);
}
static boolean cic(String a, String b) {
return containsIgnoreCase(a, b);
}
static String hpostform(Object contents, Object... params) {
return tag("form", contents, concatArrays(new Object[] {"method", "POST"}, params));
}
static String h3(String s, Object... params) {
return tag("h3", s, params) + "\n";
}
static String hinputfield(String name, Object... params) {
return htextinput(name, params);
}
static String p_nemptyLines_showFirst(int maxLines, Collection l) {
if (l(l) <= maxLines) return p_nemptyLines(l);
return p_nemptyLines(listPlus(takeFirst(maxLines, l), "..."));
}
static String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static String hdiv(Object contents, Object... params) {
return div(contents, params);
}
static java.util.Timer doLater(long delay, final Object r) {
ping();
final java.util.Timer timer = new java.util.Timer();
timer.schedule(timerTask(r, timer), delay);
return timer;
}
static java.util.Timer doLater(double delaySeconds, final Object r) {
return doLater(toMS(delaySeconds), r);
}
static String tag(String tag) {
return htag(tag);
}
static String tag(String tag, Object contents, Object... params) {
return htag(tag, str(contents), params);
}
static String tag(String tag, StringBuilder contents, Object... params) {
return htag(tag, contents, params);
}
static String tag(String tag, StringBuffer contents, Object... params) {
return htag(tag, contents, params);
}
static String tr(Object contents) {
return tag("tr", contents);
}
static String td(Object contents, Object... params) {
return tag("td", contents, params);
}
static Object[] wrapMapAsParams(Map map) {
return empty(map) ? null : new Object[] { map };
}
static A assertNempty(A a) {
return assertNempty("empty", a);
}
static A assertNempty(String msg, A a) {
if (empty(a)) throw fail(msg + ": " + a);
return a;
}
static Random random_random = new Random();
static int random(int n) {
return n <= 0 ? 0 : random_random.nextInt(n);
}
static double random(double max) {
return random()*max;
}
static double random() {
return random_random.nextInt(100001)/100000.0;
}
static double random(double min, double max) {
return min+random()*(max-min);
}
// min <= value < max
static int random(int min, int max) {
return min+random(max-min);
}
static A random(List l) {
return oneOf(l);
}
static A random(Collection c) {
if (c instanceof List) return random((List ) c);
int i = random(l(c));
return collectionGet(c, i);
}
static List filter(Iterable c, Object pred) {
if (pred instanceof F1) return filter(c, (F1 ) pred);
List x = new ArrayList();
if (c != null) for (Object o : c)
if (isTrue(callF(pred, o)))
x.add(o);
return x;
}
static List filter(Object pred, Iterable c) {
return filter(c, pred);
}
static List filter(Iterable c, F1 pred) {
List x = new ArrayList();
if (c != null) for (B o : c)
if (pred.get(o).booleanValue())
x.add(o);
return x;
}
static List filter(F1 pred, Iterable c) {
return filter(c, pred);
}
//ifclass IF1
static List filter(Iterable c, IF1 pred) {
List x = new ArrayList();
if (c != null) for (B o : c)
if (pred.get(o).booleanValue())
x.add(o);
return x;
}
static List filter(IF1 pred, Iterable c) {
return filter(c, pred);
}
//endif
static Matcher regexpIC(Pattern pat, String s) {
return pat.matcher(unnull(s));
}
static Matcher regexpIC(String pat, String s) {
return compileRegexpIC(pat).matcher(unnull(s));
}
static Pattern regexpIC(String pat) {
return compileRegexpIC(pat);
}
static boolean regexpFindIC(Pattern pat, String s) {
return regexpICFind(pat, s);
}
static boolean regexpFindIC(String pat, String s) {
return regexpICFind(pat, s);
}
static boolean eqicOneOf(String s, String... l) {
for (String x : l) if (eqic(s, x)) return true; return false;
}
public static String rtrim(String s) {
if (s == null) return null;
int i = s.length();
while (i > 0 && " \t\r\n".indexOf(s.charAt(i-1)) >= 0)
--i;
return i < s.length() ? s.substring(0, i) : s;
}
static String getSignerKey(String signed) {
String s = fullTrimLastLine(signed);
Matches m = new Matches();
if (swic_trim(s, "signer:", m)) return m.rest();
return null;
}
static Object subBot_serve500() {
return call(getMainBot(), "serve500");
}
static Object subBot_serve500(String msg) {
return call(getMainBot(), "serve500", msg);
}
static boolean isSignedWithKey_verbose = false;
static boolean isSignedWithKey(String signed, String key) {
try {
List lines = toLines(signed);
if (swic(last(lines), "signer:")) popLast(lines);
String sigLine = last(lines);
String text = fromLines(dropLast(lines));
String sig = dropPrefixMandatory("sig: ", sigLine);
return PKI.verifySignature(PKI.publicKeyFromString(key), PKI.signatureFromString(sig), toUtf8(text));
} catch (RuntimeException e) {
if (isSignedWithKey_verbose)
printStackTrace(e);
return false;
}
}
// if text trails with \n, drops the lines before that
static String dropLastTwoLines(String s) {
return dropLastLine(dropLastLine(s));
}
static Map jsonDecodeMap(String s) {
Object o = jsonDecode(s);
if (o instanceof List && empty((List) o))
return new HashMap();
if (o instanceof Map)
return (Map) o;
else
throw fail("Not a JSON map: " + s);
}
static Pair uniq2_sync(final Class c, final Object... params) {
return withDBLock(new F0>() { Pair get() { try { return uniq2(c, params); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ret uniq2(c, params);"; }});
}
static List tlft(String s) { return toLinesFullTrim(s); }
static List tlft(File f) { return toLinesFullTrim(f); }
static A conceptWhere(Class c, Object... params) {
return findConceptWhere(c, params);
}
static int countConceptsWhere(Class c, Object... params) {
return countConcepts(c, params);
}
static int countConceptsWhere() {
return countConcepts();
}
static int countConceptsWhere(String className) {
return countConcepts(className);
}
static int countConceptsWhere(Concepts concepts, String className) {
return countConcepts(concepts, className);
}
static int countConceptsWhere(Concepts concepts) {
return countConcepts(concepts);
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static List> multiSetTopPairs(MultiSet ms) {
List < Pair < A , Integer > > l = new ArrayList();
for (A a : ms.highestFirst())
l.add(pair(a, ms.get(a)));
return l;
}
static MultiSet ciMultiSet() {
MultiSet ms = new MultiSet();
ms.map = ciMap();
return ms;
}
static MultiSet ciMultiSet(Iterable l) {
return asCIMultiSet(l);
}
static Pair pairFromUglyString(String s) {
if (empty(s)) return null;
int i = indexOf(s, '|');
int lA = parseInt(takeFirst(s, i));
return pair(substring(s, i+1, i+1+lA), substring(s, i+1+lA+1));
}
static LinkedHashMap litorderedmap(Object... x) {
LinkedHashMap map = new LinkedHashMap();
litmap_impl(map, x);
return map;
}
static Collection distinctCIFieldValuesOfConcepts(Class c, String field) {
return distinctCIFieldValuesOfConcepts(db_mainConcepts(), c, field);
}
static Collection distinctCIFieldValuesOfConcepts(Concepts concepts, Class c, String field) {
// indexed
IFieldIndex index = concepts.getCIFieldIndex(c, field);
if (index != null)
return index.allValues();
// table scan
Set set = ciSet();
for (A x : concepts.list(c)) set.add((String) getOpt(x, field));
return set;
}
static List mapMultiSetByPopularity(MultiSet ms, F2 f) {
List l = new ArrayList();
if (ms != null) for (A key : ms.highestFirst())
l.add(callF(f, key, ms.get(key)));
return l;
}
static List mapMultiSetByPopularity(MultiSet ms, IF2 f) {
List l = new ArrayList();
if (ms != null) for (A key : ms.highestFirst())
l.add(callF(f, key, ms.get(key)));
return l;
}
static MultiSet distinctCIFieldValuesOfConcepts_multiSet(Class c, String field) {
return distinctCIFieldValuesOfConcepts_multiSet(db_mainConcepts(), c, field);
}
static MultiSet distinctCIFieldValuesOfConcepts_multiSet(Concepts concepts, Class c, String field) {
// indexed
IFieldIndex index = concepts.getCIFieldIndex(c, field);
if (index != null)
return index.allValues_multiSet();
// table scan
MultiSet set = ciMultiSet();
for (A x : concepts.list(c)) set.add((String) getOpt(x, field));
return set;
}
static File conceptsFile(String progID) {
return getProgramFile(progID, conceptsFileName());
}
static File conceptsFile() {
return conceptsFile(dbProgramID());
}
static List agiBlue_parseQueryScript(String script) {
return map("agiBlue_parseQueryLine",tlftj(script));
}
static TreeMap ciMap() {
return caseInsensitiveMap();
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static A getOrKeep(Map map, A a) {
if (map == null) return a;
A v = map.get(a);
return v != null ? v : a;
}
static T3 tripleMap(Object f, T3 t) {
return t == null ? null : triple(callF(f, t.a), callF(f, t.b), callF(f, t.c));
}
static T3 tripleMap(T3 t, IF1 f) {
return tripleMap(f, t);
}
static T3 tripleMap(IF1 f, T3 t) {
return t == null ? null : triple(callF(f, t.a), callF(f, t.b), callF(f, t.c));
}
static T3 tripleMap(T3 t, Object f) {
return tripleMap(f, t);
}
static boolean isDollarVar(String s) {
return startsWith(s, '$') && isJavaIdentifierAfter(s, 1);
}
static RuntimeException todo() {
throw new RuntimeException("TODO");
}
static RuntimeException todo(Object msg) {
throw new RuntimeException("TODO: " + msg);
}
static List conceptsWhereCI(Class c, Object... params) {
return findConceptsWhereCI(c, params);
}
static List conceptsWhereCI(String c, Object... params) {
return findConceptsWhereCI(c, params);
}
static List conceptsWhereCI(Concepts concepts, Class c, Object... params) {
return findConceptsWhereCI(concepts, c, params);
}
static List conceptsWhereCI(Concepts concepts, String c, Object... params) {
return findConceptsWhereCI(concepts, c, params);
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static Object subBot_serve404() {
return call(getMainBot(), "serve404");
}
static Object subBot_serve404(String msg) {
return call(getMainBot(), "serve404", msg);
}
static A optPar(ThreadLocal tl, A defaultValue) {
A a = tl.get();
if (a != null) {
tl.set(null);
return a;
}
return defaultValue;
}
static A optPar(ThreadLocal tl) {
return optPar(tl, null);
}
static Object optPar(Object[] params, String name) {
return optParam(params, name);
}
static Object optPar(String name, Object[] params) {
return optParam(params, name);
}
static Object optPar(String name, Map params) {
return optParam(name, params);
}
static A optPar(Object[] params, String name, A defaultValue) {
return optParam(params, name, defaultValue);
}
static A optPar(String name, Object[] params, A defaultValue) {
return optParam(params, name, defaultValue);
}
static int max(int a, int b) { return Math.max(a, b); }
static int max(int a, int b, int c) { return max(max(a, b), c); }
static long max(int a, long b) { return Math.max((long) a, b); }
static long max(long a, long b) { return Math.max(a, b); }
static double max(int a, double b) { return Math.max((double) a, b); }
static float max(float a, float b) { return Math.max(a, b); }
static double max(double a, double b) { return Math.max(a, b); }
static int max(Collection c) {
int x = Integer.MIN_VALUE;
for (int i : c) x = max(x, i);
return x;
}
static double max(double[] c) {
if (c.length == 0) return Double.MIN_VALUE;
double x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static float max(float[] c) {
if (c.length == 0) return Float.MAX_VALUE;
float x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static byte max(byte[] c) {
byte x = -128;
for (byte d : c) if (d > x) x = d;
return x;
}
static short max(short[] c) {
short x = -0x8000;
for (short d : c) if (d > x) x = d;
return x;
}
static int max(int[] c) {
int x = Integer.MIN_VALUE;
for (int d : c) if (d > x) x = d;
return x;
}
static int leven_limitedIC(String left, String right, int threshold) {
if (--threshold < 0) return 0;
int n = left.length(); // length of left
int m = right.length(); // length of right
// if one string is empty, the edit distance is necessarily the length
// of the other
if (n == 0)
return m <= threshold ? m : threshold+1;
if (m == 0)
return n <= threshold ? n : threshold+1;
// if length difference is > threshold, just bail out
if (abs(m-n) > threshold) return threshold+1;
if (n > m) {
// swap the two strings to consume less memory
final String tmp = left;
left = right;
right = tmp;
n = m;
m = right.length();
}
int[] p = new int[n + 1]; // 'previous' cost array, horizontally
int[] d = new int[n + 1]; // cost array, horizontally
int[] tempD; // placeholder to assist in swapping p and d
// fill in starting table values
final int boundary = Math.min(n, threshold) + 1;
for (int i = 0; i < boundary; i++) {
p[i] = i;
}
// these fills ensure that the value above the rightmost entry of our
// stripe will be ignored in following loop iterations
Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
Arrays.fill(d, Integer.MAX_VALUE);
// iterates through t - USE LONG to fix JVM SAFE POINTS.
for (long _j = 1; _j <= m; _j++) {
int j = (int) _j;
final char rightJ = right.charAt(j - 1); // jth character of right
d[0] = j;
// compute stripe indices, constrain to array size
final int min = Math.max(1, j - threshold);
final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(
n, j + threshold);
// the stripe may lead off of the table if s and t are of different
// sizes
if (min > max) {
return threshold+1;
}
// ignore entry left of leftmost
if (min > 1) {
d[min - 1] = Integer.MAX_VALUE;
}
// iterates through [min, max] in s
for (int i = min; i <= max; i++) {
if (equalsIgnoreCase(left.charAt(i - 1), rightJ)) {
// diagonally left and up
d[i] = p[i - 1];
} else {
// 1 + minimum of cell to the left, to the top, diagonally
// left and up
d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
}
}
// copy current distance counts to 'previous row' distance counts
tempD = p;
p = d;
d = tempD;
}
// if p[n] is greater than the threshold, there's no guarantee on it
// being the correct
// distance
if (p[n] <= threshold) {
return p[n];
}
return threshold+1;
}
static List keysSortedByValue(Map map) {
return keysSortedByValues(map);
}
static String quote(Object o) {
if (o == null) return "null";
return quote(str(o));
}
static String quote(String s) {
if (s == null) return "null";
StringBuilder out = new StringBuilder((int) (l(s)*1.5+2));
quote_impl(s, out);
return out.toString();
}
static void quote_impl(String s, StringBuilder out) {
out.append('"');
int l = s.length();
for (int i = 0; i < l; i++) {
char c = s.charAt(i);
if (c == '\\' || c == '"')
out.append('\\').append(c);
else if (c == '\r')
out.append("\\r");
else if (c == '\n')
out.append("\\n");
else if (c == '\0')
out.append("\\0");
else
out.append(c);
}
out.append('"');
}
static String nResults(int n) { return n2(n, "result"); }
static String nResults(Collection l) { return nResults(l(l)); }
static String htmldecode_dropAllTags(String html) {
return htmldecode(dropAllTags(html));
}
static String hfullcenter(Object contents) {
return tag("table", tr(td(contents, "align" , "center")), "width" , "100%", "height" , "100%");
}
static boolean preferCached = false;
static boolean loadSnippet_debug = false;
static ThreadLocal loadSnippet_silent = new ThreadLocal();
static int loadSnippet_timeout = 30000;
static String loadSnippet(String snippetID) { try {
if (snippetID == null) return null;
return loadSnippet(parseSnippetID(snippetID), preferCached);
} catch (Exception __e) { throw rethrow(__e); } }
static String loadSnippet(String snippetID, boolean preferCached) throws IOException {
return loadSnippet(parseSnippetID(snippetID), preferCached);
}
public static String loadSnippet(long snippetID) { try {
return loadSnippet(snippetID, preferCached);
} catch (Exception __e) { throw rethrow(__e); } }
public static String loadSnippet(long snippetID, boolean preferCached) throws IOException {
String text;
if (isLocalSnippetID(snippetID))
return loadLocalSnippet(snippetID);
IResourceLoader rl = vm_getResourceLoader();
if (rl != null)
return rl.loadSnippet(fsI(snippetID));
// boss bot disabled for now for shorter transpilations
/*text = getSnippetFromBossBot(snippetID);
if (text != null) return text;*/
initSnippetCache();
text = DiskSnippetCache_get(snippetID);
if (preferCached && text != null)
return text;
try {
if (loadSnippet_debug && text != null) System.err.println("md5: " + md5(text));
String url = tb_mainServer() + "/getraw.php?id=" + snippetID + "&utf8=1";
if (nempty(text)) url += "&md5=" + md5(text);
url += standardCredentials();
String text2 = loadSnippet_loadFromServer(url);
boolean same = eq(text2, "==*#*==");
if (loadSnippet_debug) print("loadSnippet: same=" + same);
if (!same) text = text2;
} catch (RuntimeException e) {
e.printStackTrace();
throw new IOException("Snippet #" + snippetID + " not found or not public");
}
try {
initSnippetCache();
DiskSnippetCache_put(snippetID, text);
} catch (IOException e) {
System.err.println("Minor warning: Couldn't save snippet to cache (" + DiskSnippetCache_getDir() + ")");
}
return text;
}
static File DiskSnippetCache_dir;
public static void initDiskSnippetCache(File dir) {
DiskSnippetCache_dir = dir;
dir.mkdirs();
}
public static synchronized String DiskSnippetCache_get(long snippetID) throws IOException {
return loadTextFile(DiskSnippetCache_getFile(snippetID).getPath(), null);
}
private static File DiskSnippetCache_getFile(long snippetID) {
return new File(DiskSnippetCache_dir, "" + snippetID);
}
public static synchronized void DiskSnippetCache_put(long snippetID, String snippet) throws IOException {
saveTextFile(DiskSnippetCache_getFile(snippetID).getPath(), snippet);
}
public static File DiskSnippetCache_getDir() {
return DiskSnippetCache_dir;
}
public static void initSnippetCache() {
if (DiskSnippetCache_dir == null)
initDiskSnippetCache(getGlobalCache());
}
static String loadSnippet_loadFromServer(String url) {
Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_timeout);
try {
return isTrue(loadSnippet_silent.get()) ? loadPageSilently(url) : loadPage(url);
} finally {
loadPage_forcedTimeout_byThread.set(oldTimeout);
}
}
static String form(Object contents, Object... params) {
return hform(contents, params);
}
static String htextarea(String text, Object... params) {
params = html_massageAutofocusParam(params);
return hopeningTag("textarea", params) + htmlencode2(text) + "";
}
static void logStructure(File logFile, Object o) {
logQuoted(logFile, structure(o));
}
// quick version - log to file in program directory
static void logStructure(String fileName, Object o) {
logStructure(getProgramFile(fileName), o);
}
static void logStructure(String progID, String fileName, Object o) {
logStructure(getProgramFile(progID, fileName), o);
}
static File programFile(String name) {
return prepareProgramFile(name);
}
static File programFile(String progID, String name) {
return prepareProgramFile(progID, name);
}
static boolean boolPar(ThreadLocal tl) {
return boolOptParam(tl);
}
// defaults to false
static boolean boolPar(Object[] __, String name) {
return boolOptParam(__, name);
}
static boolean boolPar(String name, Object[] __) {
return boolOptParam(__, name);
}
static boolean boolPar(String name, Map __) {
return boolOptParam(name, __);
}
static boolean boolPar(String name, Object[] params, boolean defaultValue) {
return optParam(params, name, defaultValue);
}
static boolean eqOneOf(Object o, Object... l) {
for (Object x : l) if (eq(o, x)) return true; return false;
}
static TreeMap asCIMap(Map map) {
return asCaseInsensitiveMap(map);
}
static boolean valueIs1(String key, Map map) {
return eq("1", mapGet(map, key));
}
static Object withDBLock(Object r) {
Lock __197 = db_mainConcepts().lock; lock(__197); try {
return callF(r);
} finally { unlock(__197); } }
static A withDBLock(F0 r) {
return (A) withDBLock((Object) r);
}
static Object withDBLock(Concepts concepts, Object r) {
Lock __198 = concepts.lock; lock(__198); try {
return callF(r);
} finally { unlock(__198); } }
static A withDBLock(Concepts concepts, F0 r) {
return (A) withDBLock(concepts, (Object) r);
}
static String subBot_clientIP() {
return getClientIP_subBot();
}
static boolean eq_icIf(boolean ignoreCase, String a, String b) {
return ignoreCase ? eqic(a, b) : eq(a, b);
}
static Concept cnew(String name, Object... values) {
Class extends Concept> cc = findClass(name);
Concept c = cc != null ? nuObject(cc) : new Concept(name);
csetAll(c, values);
return c;
}
static Concept cnew(Concepts concepts, String name, Object... values) {
Class extends Concept> cc = findClass(name);
concepts_unlisted.set(true);
Concept c;
try {
c = cc != null ? nuObject(cc) : new Concept(name);
} finally {
concepts_unlisted.set(null);
}
concepts.register(c);
csetAll(c, values);
return c;
}
static A cnew(Class cc, Object... values) {
A c = nuObject(cc);
csetAll(c, values);
return c;
}
static A cnew(Concepts concepts, Class cc, Object... values) {
concepts_unlisted.set(true);
A c;
try {
c = nuObject(cc);
} finally {
concepts_unlisted.set(null);
}
concepts.register(c);
csetAll(c, values);
return c;
}
static List sortByFieldInPlace(List l, String field) {
sort(l, fieldComparator(field));
return l;
}
static List sortByFieldInPlace(String field, List l) {
return sortByFieldInPlace(l, field);
}
static void numberEntriesInConceptField(String field, List extends Concept> entries) {
for (int i = 0; i < l(entries); i++)
if (getInt(entries.get(i), field) == 0)
cset(entries.get(i), field, i+1);
}
static A conceptWhereCI(Class c, Object... params) {
return findConceptWhereCI(c, params);
}
static Concept conceptWhereCI(String c, Object... params) {
return findConceptWhereCI(db_mainConcepts(), c, params);
}
static A conceptWhereCI(Concepts concepts, Class c, Object... params) {
return findConceptWhereCI(concepts, c, params);
}
static Concept conceptWhereCI(Concepts concepts, String c, Object... params) {
return findConceptWhereCI(concepts, c, params);
}
static A uniqCI_sync(final Class c, final Object... params) {
return withDBLock(new F0 () { A get() { try { return uniqCI(c, params); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ret uniqCI(c, params);"; }});
}
static List moveElementToBeginningIC(String a, Collection l) {
if (!contains(l, a)) return asList(l);
return listPlus_inFront(listMinusElementIC(a, l), a);
}
static Object first(Object list) {
return first((Iterable) list);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static A first(IterableIterator i) {
return first((Iterator ) i);
}
static A first(Iterator i) {
return i == null || !i.hasNext() ? null : i.next();
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static A first(T3 t) {
return t == null ? null : t.a;
}
static List conceptsWhere(Class c, Object... params) {
return findConceptsWhere(c, params);
}
static List conceptsWhere(String c, Object... params) {
return findConceptsWhere(c, params);
}
// returns number of changes
static int cset_sync(Concept c, Object... values) { try {
return withDBLock(c._concepts, new F0() { Integer get() { try {
return cset(c, values);
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ret cset(c, values);"; }});
} catch (Exception __e) { throw rethrow(__e); } }
static boolean isURL(String s) {
return startsWithOneOf(s, "http://", "https://", "file:");
}
static boolean isAGIDomain(String s) {
return regexpMatchesIC("[a-z0-9-]+\\.agi\\.blue", s);
}
static String fixAGILink(String s) {
if (!isAbsoluteURL(s)) return s;
String host = hostNameFromURL(s);
if (!isAGIBlueDomain(host)) return s;
String sub = dropSuffixIC(theAGIBlueDomain(), host);
if (l(sub) <= maximumDomainPartLength()) return s;
return "http://" + theAGIBlueDomain() + hquery(mapPlus(paramsFromURL(s), "domain" , host));
}
static String absoluteURL(String url) {
return isAbsoluteURL(url) ? url : "http://" + url;
}
static String htmlencode2(String s) {
return htmlencode_noQuotes(s);
}
static String agiBlue_linkForPhrase(String phrase, Object... additionalParams) {
return agiBlueURL() + hquery(arrayPlus /* allow multiple "get" parameters */(additionalParams, "q" , phrase));
}
static List sortedByField(Collection c, final String field) {
List l = new ArrayList(c);
sort(l, new Comparator () {
public int compare(A a, A b) {
return cmp(getOpt(a, field), getOpt(b, field));
}
});
return l;
}
static List sortedByField(String field, Collection c) {
return sortedByField(c, field);
}
// f: A -> Comparable
static List sortedByCalculatedField(Iterable c, Object f) {
return sortByCalculatedField(c, f);
}
static List sortedByCalculatedField(Object f, Iterable c) {
return sortedByCalculatedField(c, f);
}
static List sortedByCalculatedField(Iterable c, IF1 f) {
return sortedByCalculatedField(c, (Object) f);
}
static String hhtml(Object contents) {
return containerTag("html", contents);
}
static String hAddToHead_fast(String html, String tag) {
int idx = indexOfIC(html, "");
if (idx < 0) return tag + html;
return takeFirst(html, idx) + tag + substring(html, idx);
}
// TODO: is display=swap always correct?
static String hIncludeGoogleFont(String fontFamily) {
return htag("link","", "href" , "https://fonts.googleapis.com/css?family=" + urlencode(fontFamily) + "&display=swap", "rel" , "stylesheet");
}
static String hmobilefix() {
return " ";
}
static String hmobilefix(String html) {
return hAddToHead(html, hmobilefix());
}
static String hstylesheet(Object contents) {
return hcss(contents);
}
static boolean amProgram(String snippetID) {
return sameSnippetID(programID(), snippetID);
}
static String myLink(String uri) {
return relativeRawBotLink(programID(), uri);
}
static int randomID_defaultLength = 12;
static String randomID(int length) {
return makeRandomID(length);
}
static String randomID() {
return randomID(randomID_defaultLength);
}
static int globalIDLength() {
return 16;
}
static void db() {
conceptsAndBot();
}
// use -10000 for 10 seconds plus slowdown logic
static void db(Integer autoSaveInterval) {
conceptsAndBot(autoSaveInterval);
}
static ConceptFieldIndexCI indexConceptFieldCI(Class c, String field) {
ConceptFieldIndexCI idx = getConceptFieldCIIndex(c, field);
return idx != null ? idx : new ConceptFieldIndexCI(c, field);
}
static void indexConceptField(Class extends Concept> c, String field) {
if (!isConceptFieldIndexed(c, field))
new ConceptFieldIndex(c, field);
}
static PKIKeyPair pkiKeyPairFromTwoLineFile(File f) {
List l = tlft(loadTextFile(f));
if (l(l) == 2) return new PKIKeyPair(second(l), first(l));
return null;
}
static File agiBot_trustedKeyForMachine_file() {
return javaxSecretDir("agi.blue-trusted-key-pair.txt");
}
static boolean endsWithLetterOrDigit(String s) {
return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length()-1));
}
static void ping_okInCleanUp() {
if (ping_pauseAll || ping_anyActions )
ping_impl(true);
}
// this syntax should be removed...
static Object getThreadLocal(Object o, String name) {
ThreadLocal t = (ThreadLocal) (getOpt(o, name));
return t != null ? t.get() : null;
}
static A getThreadLocal(ThreadLocal tl) {
return tl == null ? null : tl.get();
}
static A getThreadLocal(ThreadLocal tl, A defaultValue) {
return or(getThreadLocal(tl), defaultValue);
}
static ThreadLocal print_byThread_dontCreate() {
return print_byThread;
}
static boolean isFalse(Object o) {
return eq(false, o);
}
static Map> callF_cache = newDangerousWeakHashMap();
static A callF(F0 f) {
return f == null ? null : f.get();
}
static B callF(F1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static C callF(F2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static C callF(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF(VF1 f, A a) {
if (f != null) f.get(a);
}
static Object callF(Object f, Object... args) { try {
if (f instanceof String)
return callMC((String) f, args);
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
}
if (f == null) return null;
Class c = f.getClass();
ArrayList methods;
synchronized(callF_cache) {
methods = callF_cache.get(c);
if (methods == null)
methods = callF_makeCache(c);
}
int n = l(methods);
if (n == 0) {
throw fail("No get method in " + getClassName(c));
}
if (n == 1) return invokeMethod(methods.get(0), f, args);
for (int i = 0; i < n; i++) {
Method m = methods.get(i);
if (call_checkArgs(m, args, false))
return invokeMethod(m, f, args);
}
throw fail("No matching get method in " + getClassName(c));
} catch (Exception __e) { throw rethrow(__e); } }
// used internally
static ArrayList callF_makeCache(Class c) {
ArrayList l = new ArrayList();
Class _c = c;
do {
for (Method m : _c.getDeclaredMethods())
if (m.getName().equals("get")) {
m.setAccessible(true);
l.add(m);
}
if (!l.isEmpty()) break;
_c = _c.getSuperclass();
} while (_c != null);
callF_cache.put(c, l);
return l;
}
static String fixNewLines(String s) {
int i = indexOf(s, '\r');
if (i < 0) return s;
int l = s.length();
StringBuilder out = new StringBuilder(l);
out.append(s, 0, i);
for (; i < l; i++) {
char c = s.charAt(i);
if (c != '\r')
out.append(c);
else {
out.append('\n');
if (i+1 < l && s.charAt(i+1) == '\n') ++i;
}
}
return out.toString();
}
static void print_append(Appendable _buf, String s, int max) { try {
synchronized(_buf) {
_buf.append(s);
if (!(_buf instanceof StringBuilder)) return;
rotateStringBuilder((StringBuilder) _buf, max);
}
} catch (Exception __e) { throw rethrow(__e); } }
static Object[] expandParams(Class c, Object[] params) {
if (l(params) == 1)
params = new Object[] { singleFieldName(c), params[0] };
else
warnIfOddCount(params);
return params;
}
static void warnIfOddCount(Object... list) {
if (odd(l(list)))
printStackTrace("Odd list size: " + list);
}
static Field setOpt_findField(Class c, String field) {
HashMap map;
synchronized(getOpt_cache) {
map = getOpt_cache.get(c);
if (map == null)
map = getOpt_makeCache(c);
}
return map.get(field);
}
static void setOpt(Object o, String field, Object value) { try {
if (o == null) return;
Class c = o.getClass();
HashMap map;
if (getOpt_cache == null)
map = getOpt_makeCache(c); // in class init
else synchronized(getOpt_cache) {
map = getOpt_cache.get(c);
if (map == null)
map = getOpt_makeCache(c);
}
if (map == getOpt_special) {
if (o instanceof Class) {
setOpt((Class) o, field, value);
return;
}
// It's probably a subclass of Map. Use raw method
setOpt_raw(o, field, value);
return;
}
Field f = map.get(field);
if (f != null)
smartSet(f, o, value); // possible improvement: skip setAccessible
} catch (Exception __e) { throw rethrow(__e); } }
static void setOpt(Class c, String field, Object value) {
if (c == null) return;
try {
Field f = setOpt_findStaticField(c, field);
if (f != null)
smartSet(f, null, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field setOpt_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) {
f.setAccessible(true);
return f;
}
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static Object deref(Object o) {
if (o instanceof Derefable) o = ((Derefable) o).get();
return o;
}
static String intern(String s) {
return fastIntern(s);
}
static void mapPut2(Map map, A key, B value) {
if (map != null && key != null)
if (value != null) map.put(key, value);
else map.remove(key);
}
static String assertIdentifier(String s) {
return assertIsIdentifier(s);
}
static String assertIdentifier(String msg, String s) {
return assertIsIdentifier(msg, s);
}
static boolean isSubtypeOf(Class a, Class b) {
return b.isAssignableFrom(a); // << always hated that method, let's replace it!
}
static Object derefRef(Object o) {
if (o instanceof Concept.Ref) o = ((Concept.Ref) o).get();
return o;
}
static boolean neq(Object a, Object b) {
return !eq(a, b);
}
static A uniq(Class c, Object... params) {
return uniqueConcept(c, params);
}
static A uniq(Concepts cc, Class c, Object... params) {
return uniqueConcept(cc, c, params);
}
static IterableIterator toLines(File f) {
return linesFromFile(f);
}
static List toLines(String s) {
List lines = new ArrayList();
if (s == null) return lines;
int start = 0;
while (true) {
int i = toLines_nextLineBreak(s, start);
if (i < 0) {
if (s.length() > start) lines.add(s.substring(start));
break;
}
lines.add(s.substring(start, i));
if (s.charAt(i) == '\r' && i+1 < s.length() && s.charAt(i+1) == '\n')
i += 2;
else
++i;
start = i;
}
return lines;
}
static int toLines_nextLineBreak(String s, int start) {
for (int i = start; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\r' || c == '\n')
return i;
}
return -1;
}
static A conceptWhereIC(Class c, Object... params) {
return findConceptWhereCI(c, params);
}
static Concept conceptWhereIC(String c, Object... params) {
return findConceptWhereCI(db_mainConcepts(), c, params);
}
static A conceptWhereIC(Concepts concepts, Class c, Object... params) {
return findConceptWhereCI(concepts, c, params);
}
static Concept conceptWhereIC(Concepts concepts, String c, Object... params) {
return findConceptWhereCI(concepts, c, params);
}
static String getType(Object o) {
return getClassName(o);
}
static long getFileSize(String path) {
return path == null ? 0 : new File(path).length();
}
static long getFileSize(File f) {
return f == null ? 0 : f.length();
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static A get(List l, int idx) {
return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static B get(Map map, A key) {
ret map != null ? map.get(key) : null;
}*/
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
if (o == null) return null;
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
Field f = getOpt_findField(o.getClass(), field);
if (f != null) {
f.setAccessible(true);
return f.get(o);
}
if (o instanceof DynamicObject)
return ((DynamicObject) o).fieldValues.get(field);
} catch (Exception e) {
throw asRuntimeException(e);
}
throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(Object o, String field) {
try {
Field f = get_findField(o.getClass(), field);
f.setAccessible(true);
return f.get(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
f.setAccessible(true);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static Object get(String field, Object o) {
return get(o, field);
}
static Object getOpt(Object o, String field) {
return getOpt_cached(o, field);
}
static Object getOpt(String field, Object o) {
return getOpt_cached(o, field);
}
static Object getOpt_raw(Object o, String field) { try {
Field f = getOpt_findField(o.getClass(), field);
if (f == null) return null;
f.setAccessible(true);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
// access of static fields is not yet optimized
static Object getOpt(Class c, String field) { try {
if (c == null) return null;
Field f = getOpt_findStaticField(c, field);
if (f == null) return null;
f.setAccessible(true);
return f.get(null);
} catch (Exception __e) { throw rethrow(__e); } }
static Field getOpt_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static String getClassName(Object o) {
return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
}
static int cmp(Number a, Number b) {
return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue());
}
static int cmp(double a, double b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(Object a, Object b) {
if (a == null) return b == null ? 0 : -1;
if (b == null) return 1;
return ((Comparable) a).compareTo(b);
}
static boolean checkFieldsIC(Object x, Object... data) {
for (int i = 0; i < l(data); i += 2)
if (!eqicOrEq(getOpt(x, (String) data[i]), data[i+1]))
return false;
return true;
}
static boolean instanceOf(Object o, String className) {
if (o == null) return false;
String c = o.getClass().getName();
return eq(c, className) || eq(c, "main$" + className);
}
static boolean instanceOf(Object o, Class c) {
if (c == null) return false;
return c.isInstance(o);
}
static ArrayList asList(A[] a) {
return a == null ? new ArrayList () : new ArrayList (Arrays.asList(a));
}
static ArrayList asList(int[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (int i : a) l.add(i);
return l;
}
static ArrayList asList(float[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (float i : a) l.add(i);
return l;
}
static ArrayList asList(Iterable s) {
if (s instanceof ArrayList) return (ArrayList) s;
ArrayList l = new ArrayList();
if (s != null)
for (A a : s)
l.add(a);
return l;
}
static ArrayList asList(Producer p) {
ArrayList l = new ArrayList();
A a;
if (p != null) while ((a = p.next()) != null)
l.add(a);
return l;
}
static ArrayList asList(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
static Set keys(Map map) {
return map == null ? new HashSet() : map.keySet();
}
static Set keys(Object map) {
return keys((Map) map);
}
static Set keys(MultiSet ms) {
return ms.keySet();
}
static Set keys(MultiMap mm) {
return mm.keySet();
}
static void _handleError(Error e) {
call(javax(), "_handleError", e);
}
static String domainName() {
Object session = call(getMainBot(), "getSession");
Map headers = (Map) (call(session, "getHeaders"));
String host = (String) (headers.get("host"));
if (host == null) return null;
return dropFrom(host, ":");
}
static String asString(Object o) {
return o == null ? null : o.toString();
}
static boolean endsWithIgnoreCase(String a, String b) {
int la = l(a), lb = l(b);
return la >= lb && regionMatchesIC(a, la-lb, b, 0, lb);
}
static boolean endsWithIgnoreCase(String a, String b, Matches m) {
if (!endsWithIgnoreCase(a, b)) return false;
m.m = new String[] { substring(a, 0, l(a)-l(b)) };
return true;
}
static ArrayList emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
// get correct type at once
static ArrayList emptyList(Class c) {
return new ArrayList();
}
static Map emptyMap() {
return new HashMap();
}
static B mapGet(Map map, A a) {
return map == null || a == null ? null : map.get(a);
}
static B mapGet(A a, Map map) {
return map == null || a == null ? null : map.get(a);
}
static Map subBot_getHttpFiles() {
Object session = call(getMainBot(), "getSession");
return (Map) call(session, "getFiles");
}
static Object callOpt(Object o) {
return callF(o);
}
static A callOpt(Object o, String method, Object... args) {
return (A) callOpt_withVarargs(o, method, args);
}
static Object getBot(String botID) {
return callOpt(getMainBot(), "getBot", botID);
}
// make concept instance that is not connected to DB
static A unlisted(Class c, Object... args) {
concepts_unlisted.set(true);
try {
return nuObject(c, args);
} finally {
concepts_unlisted.set(null);
}
}
static boolean startsWithIgnoreCase(String a, String b) {
return regionMatchesIC(a, 0, b, 0, b.length());
}
static String substring(String s, int x) {
return substring(s, x, strL(s));
}
static String substring(String s, int x, int y) {
if (s == null) return null;
if (x < 0) x = 0;
if (x >= s.length()) return "";
if (y < x) y = x;
if (y > s.length()) y = s.length();
return s.substring(x, y);
}
static String dropSuffix(String suffix, String s) {
return s.endsWith(suffix) ? s.substring(0, l(s)-l(suffix)) : s;
}
static String unpackAGIDomainOpt(String s) {
return or(unpackAGIDomain(s), s);
}
static boolean neqic(String a, String b) {
return !eqic(a, b);
}
static boolean neqic(char a, char b) {
return !eqic(a, b);
}
static Pair uniqCI2(Class c, Object... params) {
return uniqCI2(db_mainConcepts(), c, params);
}
static Pair uniqCI2(Concepts cc, Class c, Object... params) {
params = expandParams(c, params);
A x = findConceptWhereCI(c, params);
if (x == null) {
x = unlisted(c);
csetAll(x, params);
cc.register(x);
return pair(x, true);
}
return pair(x, false);
}
static List newSubListOrSame(List l, int startIndex) {
return newSubListOrSame(l, startIndex, l(l));
}
static List newSubListOrSame(List l, int startIndex, int endIndex) {
if (l == null) return null;
int n = l(l);
startIndex = max(0, startIndex);
endIndex = min(n, endIndex);
if (startIndex >= endIndex) return ll();
if (startIndex == 0 && endIndex == n) return l;
return cloneList(l.subList(startIndex, endIndex));
}
static String hSilentComputator() {
return hSilentComputator(hSilentComputator_defaultURI());
}
static String hSilentComputator(String wsUri) {
return hSilentComputator(wsUri, "");
}
static String hSilentComputator(String wsUri, String flag) {
if (nempty(flag)) wsUri = addSlash(wsUri) + flag;
return div("Calculating", "id" , "calcing")
+ hcss("#calcing {\r\nposition: fixed;\r\nwidth: 100%;\r\nheight: 100vh;\r\nz-index: 9999;\r\nvisibility: hidden;\r\n}")
+ hMakeComputerID()
+ hreconnectingWebSockets()
+ hjavascript("\r\n function sendPing() {\r\n ${PINGCMD}\r\n }\r\n \r\n var working = false;\r\n var benchResultl;\r\n var ws = new ReconnectingWebSocket(\"${URI}\");\r\n ws.onopen = function(event) {\r\n console.log(\"WebSocket opened.\");\r\n };\r\n ws.onmessage = function(event) {\r\n var d = event.data;\r\n while (d.length > 0 && d.charCodeAt(d.length-1) == 0)\r\n d = d.substring(0, d.length-1);\r\n console.log(\"Evaluating: \" + d);\r\n var geval = eval; // use global scope\r\n geval(d);\r\n console.log(\"Evaluated.\");\r\n };\r\n \r\n //working = true; // XXX\r\n //console.log(\"Eval test: \" + eval('working'));\r\n ".replace("${URI}", wsUri)
.replace("${PINGCMD}", nodes_pingCmd()));
}
static String hSilentComputator_defaultURI() {
int port = subBot_currentPort();
return (subBot_isHttps() ? "wss://" : "ws://") + domain()
+ (port == 80 ? "" : ":" + port) + "/";
}
static String href(String link, Object contents, Object... params) {
if (link == null) return str(contents);
return tag("a", contents, arrayPlus(params, "href", link));
}
static String himg(String src, Object... params) {
return tag("img", "", arrayPlus(params, "src", src));
}
static String snippetImageLink(String snippetID) {
return snippetImageURL(snippetID);
}
static String htmlencode_noQuotes(String s) {
if (s == null) return "";
StringBuilder out = new StringBuilder(Math.max(16, s.length()));
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '<') out.append("<");
else if (c == '>') out.append(">");
else if (c > 127 || c == '&') {
out.append("");
out.append((int) c);
out.append(';');
} else
out.append(c);
}
return out.toString();
}
static String hrefBlank(String link, Object contents, Object... params) {
return tag("a", contents, concatArrays(new Object[] { "href" , link, "target" , "_blank" }, params));
}
public static long parseSnippetID(String snippetID) {
long id = Long.parseLong(shortenSnippetID(snippetID));
if (id == 0) throw fail("0 is not a snippet ID");
return id;
}
static String n2(long l) { return formatWithThousands(l); }
static String n2(Collection l) { return n2(l(l)); }
static String n2(double l, String singular) {
return n2(l, singular, singular + "s");
}
static String n2(double l, String singular, String plural) {
if (fraction(l) == 0)
return n2((long) l, singular, plural);
else
return l + " " + plural;
}
static String n2(long l, String singular, String plural) {
return n_fancy2(l, singular, plural);
}
static String n2(long l, String singular) {
return n_fancy2(l, singular, singular + "s");
}
static String n2(Collection l, String singular) {
return n2(l(l), singular);
}
static String n2(Collection l, String singular, String plural) {
return n_fancy2(l, singular, plural);
}
static String n2(Map m, String singular, String plural) {
return n_fancy2(m, singular, plural);
}
static String n2(Map m, String singular) {
return n2(l(m), singular);
}
static String n2(Object[] a, String singular) { return n2(l(a), singular); }
static String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); }
static String n2(MultiSet ms, String singular, String plural) {
return n_fancy2(ms, singular, plural);
}
static void sort(T[] a, Comparator super T> c) {
Arrays.sort(a, c);
}
static void sort(T[] a) {
Arrays.sort(a);
}
static void sort(List a, Comparator super T> c) {
Collections.sort(a, c);
}
static void sort(List a) {
Collections.sort(a);
}
static Comparator descFieldComparator(final String field) {
return new Comparator () {
public int compare(A a, A b) {
return cmp(getOpt(b, field), getOpt(a, field));
}
};
}
static volatile Concepts mainConcepts; // Where we create new concepts
static Concepts db_mainConcepts() {
if (mainConcepts == null) {
mainConcepts = new Concepts(getDBProgramID());
mainConcepts.classFinder = _defaultClassFinder();
}
return mainConcepts;
}
static boolean contains(Collection c, Object o) {
return c != null && c.contains(o);
}
static boolean contains(Object[] x, Object o) {
if (x != null)
for (Object a : x)
if (eq(a, o))
return true;
return false;
}
static boolean contains(String s, char c) {
return s != null && s.indexOf(c) >= 0;
}
static boolean contains(String s, String b) {
return s != null && s.indexOf(b) >= 0;
}
static boolean contains(BitSet bs, int i) {
return bs != null && bs.get(i);
}
static String urlencode(String x) {
try {
return URLEncoder.encode(unnull(x), "UTF-8");
} catch (UnsupportedEncodingException e) { throw new RuntimeException(e); }
}
static String stringPar(Object[] params, String name) {
return stringOptPar(params, name);
}
static String stringPar(String name, Object[] params) {
return stringOptPar(params, name);
}
static String stringPar(String name, Map params) {
return (String) optPar(name, params);
}
static String stringPar(String name, Object[] params, String defaultValue) {
return optPar(name, params, defaultValue);
}
static String htmlencode(Object o) {
return htmlencode(str(o));
}
static String htmlencode(String s) {
if (s == null) return "";
StringBuilder out = new StringBuilder(Math.max(16, s.length()));
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
/*if (c >= 0x100)
out.append("").append(charToHex(c)).append(';');
else*/ if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&')
out.append("").append((int) c).append(';');
else
out.append(c);
}
return out.toString();
}
static String unicode_leftPointingTriangle() {
return unicodeFromCodePoint(0x25C2);
}
static String unicode_rightPointingTriangle() {
return charToString(0x25B8);
}
static String lines(Iterable lines) { return fromLines(lines); }
static String lines(Object[] lines) { return fromLines(asList(lines)); }
static List lines(String s) { return toLines(s); }
static float abs(float f) { return Math.abs(f); }
static int abs(int i) { return Math.abs(i); }
static double abs(double d) { return Math.abs(d); }
static Object call(Object o) {
return callF(o);
}
// varargs assignment fixer for a single string array argument
static Object call(Object o, String method, String[] arg) {
return call(o, method, new Object[] {arg});
}
static Object call(Object o, String method, Object... args) {
//ret call_cached(o, method, args);
return call_withVarargs(o, method, args);
}
static String hhead(Object contents) {
return tag("head", contents);
}
static String htitle(String title) {
return tag("title", htmlencode_noQuotes(title));
}
static String htag(String tag) {
return htag(tag, "");
}
static String htag(String tag, Object contents, Object... params) {
String openingTag = hopeningTag(tag, params);
String s = str(contents);
if (empty(s) && neqic(tag, "script"))
return dropLast(openingTag) + "/>";
return openingTag + s + "" + tag + ">";
}
static boolean odd(int i) {
return (i & 1) != 0;
}
static boolean odd(long i) {
return (i & 1) != 0;
}
static boolean odd(BigInteger i) { return odd(toInt(i)); }
static String[] dropFirst(int n, String[] a) {
return drop(n, a);
}
static String[] dropFirst(String[] a) {
return drop(1, a);
}
static Object[] dropFirst(Object[] a) {
return drop(1, a);
}
static List dropFirst(List l) {
return dropFirst(1, l);
}
static List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); }
static List dropFirst(Iterable i) { return dropFirst(toList(i)); }
static List dropFirst(int n, List l) {
return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size()));
}
static List dropFirst(List l, int n) {
return dropFirst(n, l);
}
static String dropFirst(int n, String s) { return substring(s, n); }
static String dropFirst(String s, int n) { return substring(s, n); }
static String dropFirst(String s) { return substring(s, 1); }
static Object[] html_massageAutofocusParam(Object[] params) {
Object autofocus = optPar("autofocus",params);
return changeParam(params, "autofocus" , eqOneOf(autofocus, true, 1, "1", "autofocus") ? html_valueLessParam() : null);
}
static Object[] concatArrays(Object[]... arrays) {
int l = 0;
for (Object[] a : arrays) l += l(a);
Object[] x = new Object[l];
int i = 0;
for (Object[] a : arrays) if (a != null) {
System.arraycopy(a, 0, x, i, l(a));
i += l(a);
}
return x;
}
static String nlToBr(String s) {
return s.replace("\n", " \n");
}
static String nemptyLines(Iterable l) {
return lines(nempties(allToString(l)));
}
static int indexOf(List l, A a, int startIndex) {
if (l == null) return -1;
int n = l(l);
for (int i = startIndex; i < n; i++)
if (eq(l.get(i), a))
return i;
return -1;
}
static int indexOf(List l, int startIndex, A a) {
return indexOf(l, a, startIndex);
}
static int indexOf(List l, A a) {
if (l == null) return -1;
return l.indexOf(a);
}
static int indexOf(String a, String b) {
return a == null || b == null ? -1 : a.indexOf(b);
}
static int indexOf(String a, String b, int i) {
return a == null || b == null ? -1 : a.indexOf(b, i);
}
static int indexOf(String a, char b) {
return a == null ? -1 : a.indexOf(b);
}
static int indexOf(String a, int i, char b) {
return indexOf(a, b, i);
}
static int indexOf(String a, char b, int i) {
return a == null ? -1 : a.indexOf(b, i);
}
static int indexOf(String a, int i, String b) {
return a == null || b == null ? -1 : a.indexOf(b, i);
}
static int indexOf(A[] x, A a) {
int n = l(x);
for (int i = 0; i < n; i++)
if (eq(x[i], a))
return i;
return -1;
}
static boolean even(int i) {
return (i & 1) == 0;
}
static boolean even(long i) {
return (i & 1) == 0;
}
static A or(A a, A b) {
return a != null ? a : b;
}
static TreeSet toCaseInsensitiveSet(Iterable c) {
if (isCISet(c)) return (TreeSet) c;
TreeSet set = caseInsensitiveSet();
addAll(set, c);
return set;
}
static TreeSet toCaseInsensitiveSet(String... x) {
TreeSet set = caseInsensitiveSet();
addAll(set, x);
return set;
}
static List filterNempty(Collection c) {
List l = new ArrayList();
for (String x : unnull(c))
if (nempty(x))
l.add(x);
return l;
}
static MultiMap decodeHQueryToMultiMap(String query) {
MultiMap map = new MultiMap();
for (String s : splitAtAmpersand(query)) {
int i = s.indexOf('=');
if (i >= 0)
map.put(urldecode(s.substring(0, i)), urldecode(s.substring(i+1)));
}
return map;
}
static Object serveJSON_shallowLineBreaks(Object data) {
return serveText(jsonEncode_shallowLineBreaks(data));
}
static List collectField(Collection c, String field) {
List l = new ArrayList();
if (c != null) for (Object a : c)
l.add(getOpt(a, field));
return l;
}
static List collectField(String field, Collection c) {
return collectField(c, field);
}
static boolean checkCondition(Object condition, Object... args) {
return isTrue(callF(condition, args));
}
static boolean checkCondition(IF1 condition, A arg) {
return isTrue(callF(condition, arg));
}
static boolean isSquareBracketed(String s) {
return s != null && s.startsWith("[") && s.endsWith("]");
}
static boolean isInteger(String s) {
int n = l(s);
if (n == 0) return false;
int i = 0;
if (s.charAt(0) == '-')
if (++i >= n) return false;
while (i < n) {
char c = s.charAt(i);
if (c < '0' || c > '9') return false;
++i;
}
return true;
}
static String deSquareBracket(String s) {
if (startsWith(s, "[") && endsWith(s, "]"))
return substring(s, 1, l(s)-1);
return s;
}
static List filterConceptsIC(List list, Object... params) {
List l = new ArrayList();
for (A x : list)
if (checkConceptFieldsIC(x, params))
l.add(x);
return l;
}
// magic cast
static A cget(Object c, String field) {
Object o = getOpt(c, field);
if (o instanceof Concept.Ref) return (A) ((Concept.Ref) o).get();
return (A) o;
}
static A cget(String field, Object c) {
return cget(c, field);
}
static Object dm_getModule(Object moduleOrID) {
if (moduleOrID == null || eq(moduleOrID, "")) return null;
if (isString(moduleOrID) && isIdentifier(((String) moduleOrID)))
return dm_getService(((String) moduleOrID));
if (isStringOrIntOrLong(moduleOrID))
return dm_callOS("getDynModuleByID", str(moduleOrID));
return dm_resolveModule(moduleOrID);
}
static AutoCloseable dm_enter(Object mod) {
return (AutoCloseable) callOpt(dm_getModule(mod), "enter");
}
static Object call_withVarargs(Object o, String method, Object... args) { try {
if (o == null) return null;
if (o instanceof Class) {
Class c = (Class) o;
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findStaticMethod(method, args);
if (me != null)
return invokeMethod(me, null, args);
// try varargs
List methods = cache.cache.get(method);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
{ if (!(isStaticMethod(m))) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, null, newArgs);
}
throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found");
} else {
Class c = o.getClass();
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(method, args);
if (me != null)
return invokeMethod(me, o, args);
// try varargs
List methods = cache.cache.get(method);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, o, newArgs);
}
throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found in " + c);
}
} catch (Exception __e) { throw rethrow(__e); } }
static void _close(AutoCloseable c) {
if (c != null) try {
c.close();
} catch (Throwable e) {
// Some classes stupidly throw an exception on double-closing
if (c instanceof javax.imageio.stream.ImageOutputStream)
return;
else throw rethrow(e);
}
}
static String programID;
static String getProgramID() {
return nempty(programID) ? formatSnippetIDOpt(programID) : "?";
}
// TODO: ask JavaX instead
static String getProgramID(Class c) {
String id = (String) getOpt(c, "programID");
if (nempty(id))
return formatSnippetID(id);
return "?";
}
static String getProgramID(Object o) {
return getProgramID(getMainClass(o));
}
static Object[] paramsPlus(Object[] a1, Object... a2) {
if (a2 == null) return a1;
if (a1 == null) return a2;
if (l(a1) == 1 && a1[0] instanceof Map)
return new Object[] { mapPlus((Map) a1[0], a2) };
assertEvenLength(a1);
assertEvenLength(a2);
Map map = paramsToOrderedMap(a1);
int n = l(a2);
for (int i = 0; i < n; i += 2) {
Object key = a2[i];
if (key != null) map.put(key, a2[i+1]);
}
return mapToParams(map);
}
static String htmlQuery(Map params) {
return empty(params) ? "" : "?" + makePostData(params);
}
static String htmlQuery(Object... data) {
return empty(data) ? "" : "?" + makePostData(data);
}
static int min(int a, int b) {
return Math.min(a, b);
}
static long min(long a, long b) {
return Math.min(a, b);
}
static float min(float a, float b) { return Math.min(a, b); }
static float min(float a, float b, float c) { return min(min(a, b), c); }
static double min(double a, double b) {
return Math.min(a, b);
}
static double min(double[] c) {
double x = Double.MAX_VALUE;
for (double d : c) x = Math.min(x, d);
return x;
}
static float min(float[] c) {
float x = Float.MAX_VALUE;
for (float d : c) x = Math.min(x, d);
return x;
}
static byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x) x = d;
return x;
}
static short min(short[] c) {
short x = 0x7FFF;
for (short d : c) if (d < x) x = d;
return x;
}
static int min(int[] c) {
int x = Integer.MAX_VALUE;
for (int d : c) if (d < x) x = d;
return x;
}
static boolean containsIgnoreCase(Collection l, String s) {
if (l != null) for (String x : l)
if (eqic(x, s))
return true;
return false;
}
static boolean containsIgnoreCase(String[] l, String s) {
if (l != null) for (String x : l)
if (eqic(x, s))
return true;
return false;
}
static boolean containsIgnoreCase(String s, char c) {
return indexOfIgnoreCase(s, String.valueOf(c)) >= 0;
}
static boolean containsIgnoreCase(String a, String b) {
return indexOfIgnoreCase(a, b) >= 0;
}
static List listPlus(Collection l, A... more) {
return concatLists(l, asList(more));
}
static String div(Object contents, Object... params) {
return hfulltag("div", contents, params);
}
static BigInteger div(BigInteger a, BigInteger b) {
return a.divide(b);
}
static BigInteger div(BigInteger a, int b) {
return a.divide(bigint(b));
}
//sbool ping_actions_shareable = true;
static volatile boolean ping_pauseAll = false;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions = false;
static Map ping_actions = newWeakHashMap();
static ThreadLocal ping_isCleanUpThread = new ThreadLocal();
// always returns true
static boolean ping() {
if (ping_pauseAll || ping_anyActions ) ping_impl(true /* XXX */);
//ifndef LeanMode ping_impl(); endifndef
return true;
}
// returns true when it slept
static boolean ping_impl(boolean okInCleanUp) { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) { // don't allow sharing ping_actions
if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get()))
failIfUnlicensed();
Object action = null;
synchronized(ping_actions) {
if (!ping_actions.isEmpty()) {
action = ping_actions.get(currentThread());
if (action instanceof Runnable)
ping_actions.remove(currentThread());
if (ping_actions.isEmpty()) ping_anyActions = false;
}
}
if (action instanceof Runnable)
((Runnable) action).run();
else if (eq(action, "cancelled"))
throw fail("Thread cancelled.");
}
return false;
} catch (Exception __e) { throw rethrow(__e); } }
static TimerTask timerTask(final Object r, final java.util.Timer timer) {
return new TimerTask() {
public void run() {
if (!licensed())
timer.cancel();
else
pcallF(r);
}
};
}
static long toMS(double seconds) {
return (long) (seconds*1000);
}
static A oneOf(List l) {
return l.isEmpty() ? null : l.get(new Random().nextInt(l.size()));
}
static char oneOf(String s) {
return empty(s) ? '?' : s.charAt(random(l(s)));
}
static String oneOf(String... l) {
return oneOf(asList(l));
}
static A collectionGet(Collection c, int idx) {
if (c == null || idx < 0 || idx >= l(c)) return null;
if (c instanceof List) return listGet((List ) c, idx);
Iterator it = c.iterator();
for (int i = 0; i < idx; i++) if (it.hasNext()) it.next(); else return null;
return it.hasNext() ? it.next() : null;
}
static boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
if (o instanceof ThreadLocal)
return isTrue(((ThreadLocal) o).get());
throw fail(getClassName(o));
}
static Map compileRegexpIC_cache = syncMRUCache(10);
static java.util.regex.Pattern compileRegexpIC(String pat) {
java.util.regex.Pattern p = compileRegexpIC_cache.get(pat);
if (p == null) {
try {
compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE));
} catch (PatternSyntaxException e) {
throw rethrow(wrapPatternSyntaxException(e));
}
}
return p;
}
static boolean regexpICFind(Pattern pat, String s) {
return regexpIC(pat, s).find();
}
static boolean regexpICFind(String pat, String s) {
return regexpIC(pat, s).find();
}
static String fullTrimLastLine(String s) {
return trimLastLine(rtrim(s));
}
static boolean swic_trim(String a, String b, Matches m) {
if (!swic(a, b)) return false;
m.m = new String[] {trim(substring(a, l(b)))};
return true;
}
static Object mainBot;
static Object getMainBot() {
return mainBot;
}
static A last(List l) {
return empty(l) ? null : l.get(l.size()-1);
}
static char last(String s) {
return empty(s) ? '#' : s.charAt(l(s)-1);
}
static int last(int[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static A last(A[] a) {
return l(a) != 0 ? a[l(a)-1] : null;
}
static A last(Iterator it) {
A a = null;
while (it.hasNext()) { ping(); a = it.next(); }
return a;
}
static A popLast(List l) {
return liftLast(l);
}
// usually L
static String fromLines(Iterable lines) {
StringBuilder buf = new StringBuilder();
if (lines != null)
for (Object line : lines)
buf.append(str(line)).append('\n');
return buf.toString();
}
static String fromLines(String... lines) {
return fromLines(asList(lines));
}
static String[] dropLast(String[] a, int n) {
n = Math.min(n, a.length);
String[] b = new String[a.length-n];
System.arraycopy(a, 0, b, 0, b.length);
return b;
}
static List dropLast(List l) {
return subList(l, 0, l(l)-1);
}
static List dropLast(int n, List l) {
return subList(l, 0, l(l)-n);
}
static List dropLast(Iterable l) {
return dropLast(asList(l));
}
static String dropLast(String s) {
return substring(s, 0, l(s)-1);
}
static String dropLast(String s, int n) {
return substring(s, 0, l(s)-n);
}
static String dropLast(int n, String s) {
return dropLast(s, n);
}
static String dropPrefixMandatory(String prefix, String s) {
if (s.startsWith(prefix))
return s.substring(prefix.length());
else
throw fail("Prefix " + prefix + " not found in: " + s);
}
static byte[] toUtf8(String s) { try {
return s.getBytes("UTF-8");
} catch (Exception __e) { throw rethrow(__e); } }
static Throwable printStackTrace(Throwable e) {
// we go to system.out now - system.err is nonsense
print(getStackTrace(e));
return e;
}
static void printStackTrace() {
printStackTrace(new Throwable());
}
static void printStackTrace(String msg) {
printStackTrace(new Throwable(msg));
}
static void printStackTrace(String msg, Throwable e) {
printStackTrace(new Throwable(msg, e));
}
// if text trails with \n, drops the line before that
static String dropLastLine(String s) {
s = dropSuffix("\r", dropSuffix("\n", s));
int i = s.lastIndexOf('\n');
return i < 0 ? "" : dropSuffix("\r", substring(s, 0, i));
}
static boolean jsonDecode_useOrderedMaps = true;
static Object jsonDecode(final String text) {
final List tok = jsonTok(text);
if (l(tok) == 1) return null;
class Y {
int i = 1;
Object parse() {
String t = tok.get(i);
if (t.startsWith("\"")) {
String s = unquote(tok.get(i));
i += 2;
return s;
}
if (t.equals("{"))
return parseMap();
if (t.equals("["))
return this.parseList(); // avoid loading standard function "parseList"
if (t.equals("null")) {
i += 2; return null;
}
if (t.equals("false")) {
i += 2; return false;
}
if (t.equals("true")) {
i += 2; return true;
}
boolean minus = false;
if (t.equals("-")) {
minus = true;
i += 2;
t = get(tok, i);
}
if (isInteger(t)) {
i += 2;
if (eq(get(tok, i), ".")) {
String x = t + "." + get(tok, i+2);
i += 4;
double d = parseDouble(x);
if (minus) d = -d;
return d;
} else {
long l = parseLong(t);
if (minus) l = -l;
return l != (int) l ? new Long(l) : new Integer((int) l);
}
}
throw new RuntimeException("Unknown token " + (i+1) + ": " + t + ": " + text);
}
Object parseList() {
consume("[");
List list = new ArrayList();
while (!tok.get(i).equals("]")) {
list.add(parse());
if (tok.get(i).equals(",")) i += 2;
}
consume("]");
return list;
}
Object parseMap() {
consume("{");
Map map = jsonDecode_useOrderedMaps ? new LinkedHashMap() : new TreeMap();
while (!tok.get(i).equals("}")) {
String key = unquote(tok.get(i));
i += 2;
consume(":");
Object value = parse();
map.put(key, value);
if (tok.get(i).equals(",")) i += 2;
}
consume("}");
return map;
}
void consume(String s) {
if (!tok.get(i).equals(s)) {
String prevToken = i-2 >= 0 ? tok.get(i-2) : "";
String nextTokens = join(tok.subList(i, Math.min(i+4, tok.size())));
throw fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");
}
i += 2;
}
}
return new Y().parse();
}
static Pair uniq2(Class c, Object... params) {
return uniq2(db_mainConcepts(), c, params);
}
static Pair uniq2(Concepts cc, Class c, Object... params) {
params = expandParams(c, params);
A x = findConceptWhere(c, params);
if (x == null) {
x = unlisted(c);
csetAll(x, params);
cc.register(x);
return pair(x, true);
}
return pair(x, false);
}
static List toLinesFullTrim(String s) {
List l = new ArrayList();
for (String line : toLines(s)) if (nempty(line = trim(line))) l.add(line);
return l;
}
static List toLinesFullTrim(File f) {
List l = new ArrayList();
for (String line : linesFromFile(f)) if (nempty(line = trim(line))) l.add(line);
return l;
}
// TODO: if field is a Ref<>, you can thoretically use findBackRefs
static A findConceptWhere(Class c, Object... params) {
return findConceptWhere(db_mainConcepts(), c, params);
}
static A findConceptWhere(Concepts concepts, Class c, Object... params) {
params = expandParams(c, params);
// indexed
if (concepts.fieldIndices != null)
for (int i = 0; i < l(params); i += 2) {
IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]);
if (index != null) {
for (A x : index.getAll(params[i+1]))
if (checkConceptFields(x, params)) return x;
return null;
}
}
// table scan
for (A x : concepts.list(c)) if (checkConceptFields(x, params)) return x;
return null;
}
static Concept findConceptWhere(Concepts concepts, String c, Object... params) {
for (Concept x : concepts.list(c)) if (checkConceptFields(x, params)) return x;
return null;
}
static MultiSet asCIMultiSet(Iterable l) {
MultiSet ms = new MultiSet();
ms.map = ciMap();
ms.addAll(l);
return ms;
}
static TreeSet ciSet() {
return caseInsensitiveSet();
}
static File getProgramFile(String progID, String fileName) {
if (new File(fileName).isAbsolute())
return new File(fileName);
return new File(getProgramDir(progID), fileName);
}
static File getProgramFile(String fileName) {
return getProgramFile(getProgramID(), fileName);
}
static String conceptsFileName() {
return "concepts.structure.gz";
}
static String dbProgramID() {
return getDBProgramID();
}
static ALQLLine agiBlue_parseQueryLine(String s) {
List tok = javaTokWithBrackets(s);
// TODO: improve jmatch and use here
if (lCodeTokens(tok) == 2 && eqGet(tok, 1, "return") && isIdentifier(get(tok, 3)))
return new ALQLReturn(tok.get(3));
T3 t = agiBlue_parseTriple(tok);
if (t != null)
return new ALQLTriple(t);
if (lCodeTokens(tok) == 2 && eqGet(tok, 1, "lock")) {
t = agiBlue_parseTriple(uncurly(tok.get(3)));
if (t == null) throw fail("Bad lock statement: " + s);
return new ALQLLockStatement(t);
}
throw fail("Can't parse ALQL line: " + s);
}
static List tlftj(String text) {
return toLinesFullTrim_java(text);
}
static TreeMap caseInsensitiveMap() {
return new TreeMap(caseInsensitiveComparator());
}
static T3 triple(A a, B b, C c) {
return new T3(a, b, c);
}
static boolean startsWith(String a, String b) {
return a != null && a.startsWith(b);
}
static boolean startsWith(String a, char c) {
return nemptyString(a) && a.charAt(0) == c;
}
static boolean startsWith(String a, String b, Matches m) {
if (!startsWith(a, b)) return false;
m.m = new String[] {substring(a, strL(b))};
return true;
}
static boolean startsWith(List a, List b) {
if (a == null || listL(b) > listL(a)) return false;
for (int i = 0; i < listL(b); i++)
if (neq(a.get(i), b.get(i)))
return false;
return true;
}
static boolean isJavaIdentifierAfter(String s, int i) {
int n = l(s);
if (i >= n || !Character.isJavaIdentifierStart(s.charAt(i)))
return false;
for (i++; i < n; i++)
if (!Character.isJavaIdentifierPart(s.charAt(i)))
return false;
return true;
}
static List findConceptsWhereCI(Class c, Object... params) {
return findConceptsWhereCI(db_mainConcepts(), c, params);
}
static List findConceptsWhereCI(String c, Object... params) {
return findConceptsWhereCI(db_mainConcepts(), c, params);
}
static List findConceptsWhereCI(Concepts concepts, Class c, Object... params) {
params = expandParams(c, params);
// indexed
if (concepts.ciFieldIndices != null)
for (int i = 0; i < l(params); i += 2) {
IFieldIndex index = concepts.getCIFieldIndex(c, (String) params[i]);
if (index != null) {
List rawList = index.getAll(params[i+1]);
params = dropEntryFromParams(params, i);
if (params == null) return rawList;
List l = new ArrayList();
for (A x : rawList)
if (checkConceptFieldsIC(x, params)) l.add(x);
return l;
}
}
// table scan
return filterConceptsIC(concepts.list(c), params);
}
static List findConceptsWhereCI(Concepts concepts, String c, Object... params) {
return filterConceptsIC(concepts.list(c), params);
}
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static A optParam(ThreadLocal tl, A defaultValue) {
return optPar(tl, defaultValue);
}
static A optParam(ThreadLocal tl) {
return optPar(tl);
}
static Object optParam(String name, Map params) {
return mapGet(params, name);
}
// now also takes a map as single array entry
static A optParam(Object[] opt, String name, A defaultValue) {
int n = l(opt);
if (n == 1 && opt[0] instanceof Map) {
Map map = (Map) (opt[0]);
return map.containsKey(name) ? (A) map.get(name) : defaultValue;
}
if (!even(l(opt))) throw fail("Odd parameter length");
for (int i = 0; i < l(opt); i += 2)
if (eq(opt[i], name))
return (A) opt[i+1];
return defaultValue;
}
static Object optParam(Object[] opt, String name) {
return optParam(opt, name, null);
}
static boolean equalsIgnoreCase(String a, String b) {
return eqic(a, b);
}
static boolean equalsIgnoreCase(char a, char b) {
return eqic(a, b);
}
static List keysSortedByValues(final Map map) {
List l = new ArrayList(map.keySet());
sort(l, mapComparator(map));
return l;
}
static String htmldecode(final String input) {
if (input == null) return null;
final int MIN_ESCAPE = 2;
final int MAX_ESCAPE = 6;
StringWriter writer = null;
int len = input.length();
int i = 1;
int st = 0;
while (true) {
// look for '&'
while (i < len && input.charAt(i-1) != '&')
i++;
if (i >= len)
break;
// found '&', look for ';'
int j = i;
while (j < len && j < i + MAX_ESCAPE + 1 && input.charAt(j) != ';')
j++;
if (j == len || j < i + MIN_ESCAPE || j == i + MAX_ESCAPE + 1) {
i++;
continue;
}
// found escape
if (input.charAt(i) == '#') {
// numeric escape
int k = i + 1;
int radix = 10;
final char firstChar = input.charAt(k);
if (firstChar == 'x' || firstChar == 'X') {
k++;
radix = 16;
}
try {
int entityValue = Integer.parseInt(input.substring(k, j), radix);
if (writer == null)
writer = new StringWriter(input.length());
writer.append(input.substring(st, i - 1));
if (entityValue > 0xFFFF) {
final char[] chrs = Character.toChars(entityValue);
writer.write(chrs[0]);
writer.write(chrs[1]);
} else {
writer.write(entityValue);
}
} catch (NumberFormatException ex) {
i++;
continue;
}
}
else {
// named escape
CharSequence value = htmldecode_lookupMap.get(input.substring(i, j));
if (value == null) {
i++;
continue;
}
if (writer == null)
writer = new StringWriter(input.length());
writer.append(input.substring(st, i - 1));
writer.append(value);
}
// skip escape
st = j + 1;
i = st;
}
if (writer != null) {
writer.append(input.substring(st, len));
return writer.toString();
}
return input;
}
private static final String[][] htmldecode_ESCAPES = {
{"\"", "quot"}, // " - double-quote
{"&", "amp"}, // & - ampersand
{"<", "lt"}, // < - less-than
{">", "gt"}, // > - greater-than
// Mapping to escape ISO-8859-1 characters to their named HTML 3.x equivalents.
{"\u00A0", "nbsp"}, // non-breaking space
{"\u00A1", "iexcl"}, // inverted exclamation mark
{"\u00A2", "cent"}, // cent sign
{"\u00A3", "pound"}, // pound sign
{"\u00A4", "curren"}, // currency sign
{"\u00A5", "yen"}, // yen sign = yuan sign
{"\u00A6", "brvbar"}, // broken bar = broken vertical bar
{"\u00A7", "sect"}, // section sign
{"\u00A8", "uml"}, // diaeresis = spacing diaeresis
{"\u00A9", "copy"}, // copyright sign
{"\u00AA", "ordf"}, // feminine ordinal indicator
{"\u00AB", "laquo"}, // left-pointing double angle quotation mark = left pointing guillemet
{"\u00AC", "not"}, // not sign
{"\u00AD", "shy"}, // soft hyphen = discretionary hyphen
{"\u00AE", "reg"}, // registered trademark sign
{"\u00AF", "macr"}, // macron = spacing macron = overline = APL overbar
{"\u00B0", "deg"}, // degree sign
{"\u00B1", "plusmn"}, // plus-minus sign = plus-or-minus sign
{"\u00B2", "sup2"}, // superscript two = superscript digit two = squared
{"\u00B3", "sup3"}, // superscript three = superscript digit three = cubed
{"\u00B4", "acute"}, // acute accent = spacing acute
{"\u00B5", "micro"}, // micro sign
{"\u00B6", "para"}, // pilcrow sign = paragraph sign
{"\u00B7", "middot"}, // middle dot = Georgian comma = Greek middle dot
{"\u00B8", "cedil"}, // cedilla = spacing cedilla
{"\u00B9", "sup1"}, // superscript one = superscript digit one
{"\u00BA", "ordm"}, // masculine ordinal indicator
{"\u00BB", "raquo"}, // right-pointing double angle quotation mark = right pointing guillemet
{"\u00BC", "frac14"}, // vulgar fraction one quarter = fraction one quarter
{"\u00BD", "frac12"}, // vulgar fraction one half = fraction one half
{"\u00BE", "frac34"}, // vulgar fraction three quarters = fraction three quarters
{"\u00BF", "iquest"}, // inverted question mark = turned question mark
{"\u00C0", "Agrave"}, // ? - uppercase A, grave accent
{"\u00C1", "Aacute"}, // ? - uppercase A, acute accent
{"\u00C2", "Acirc"}, // ? - uppercase A, circumflex accent
{"\u00C3", "Atilde"}, // ? - uppercase A, tilde
{"\u00C4", "Auml"}, // ? - uppercase A, umlaut
{"\u00C5", "Aring"}, // ? - uppercase A, ring
{"\u00C6", "AElig"}, // ? - uppercase AE
{"\u00C7", "Ccedil"}, // ? - uppercase C, cedilla
{"\u00C8", "Egrave"}, // ? - uppercase E, grave accent
{"\u00C9", "Eacute"}, // ? - uppercase E, acute accent
{"\u00CA", "Ecirc"}, // ? - uppercase E, circumflex accent
{"\u00CB", "Euml"}, // ? - uppercase E, umlaut
{"\u00CC", "Igrave"}, // ? - uppercase I, grave accent
{"\u00CD", "Iacute"}, // ? - uppercase I, acute accent
{"\u00CE", "Icirc"}, // ? - uppercase I, circumflex accent
{"\u00CF", "Iuml"}, // ? - uppercase I, umlaut
{"\u00D0", "ETH"}, // ? - uppercase Eth, Icelandic
{"\u00D1", "Ntilde"}, // ? - uppercase N, tilde
{"\u00D2", "Ograve"}, // ? - uppercase O, grave accent
{"\u00D3", "Oacute"}, // ? - uppercase O, acute accent
{"\u00D4", "Ocirc"}, // ? - uppercase O, circumflex accent
{"\u00D5", "Otilde"}, // ? - uppercase O, tilde
{"\u00D6", "Ouml"}, // ? - uppercase O, umlaut
{"\u00D7", "times"}, // multiplication sign
{"\u00D8", "Oslash"}, // ? - uppercase O, slash
{"\u00D9", "Ugrave"}, // ? - uppercase U, grave accent
{"\u00DA", "Uacute"}, // ? - uppercase U, acute accent
{"\u00DB", "Ucirc"}, // ? - uppercase U, circumflex accent
{"\u00DC", "Uuml"}, // ? - uppercase U, umlaut
{"\u00DD", "Yacute"}, // ? - uppercase Y, acute accent
{"\u00DE", "THORN"}, // ? - uppercase THORN, Icelandic
{"\u00DF", "szlig"}, // ? - lowercase sharps, German
{"\u00E0", "agrave"}, // ? - lowercase a, grave accent
{"\u00E1", "aacute"}, // ? - lowercase a, acute accent
{"\u00E2", "acirc"}, // ? - lowercase a, circumflex accent
{"\u00E3", "atilde"}, // ? - lowercase a, tilde
{"\u00E4", "auml"}, // ? - lowercase a, umlaut
{"\u00E5", "aring"}, // ? - lowercase a, ring
{"\u00E6", "aelig"}, // ? - lowercase ae
{"\u00E7", "ccedil"}, // ? - lowercase c, cedilla
{"\u00E8", "egrave"}, // ? - lowercase e, grave accent
{"\u00E9", "eacute"}, // ? - lowercase e, acute accent
{"\u00EA", "ecirc"}, // ? - lowercase e, circumflex accent
{"\u00EB", "euml"}, // ? - lowercase e, umlaut
{"\u00EC", "igrave"}, // ? - lowercase i, grave accent
{"\u00ED", "iacute"}, // ? - lowercase i, acute accent
{"\u00EE", "icirc"}, // ? - lowercase i, circumflex accent
{"\u00EF", "iuml"}, // ? - lowercase i, umlaut
{"\u00F0", "eth"}, // ? - lowercase eth, Icelandic
{"\u00F1", "ntilde"}, // ? - lowercase n, tilde
{"\u00F2", "ograve"}, // ? - lowercase o, grave accent
{"\u00F3", "oacute"}, // ? - lowercase o, acute accent
{"\u00F4", "ocirc"}, // ? - lowercase o, circumflex accent
{"\u00F5", "otilde"}, // ? - lowercase o, tilde
{"\u00F6", "ouml"}, // ? - lowercase o, umlaut
{"\u00F7", "divide"}, // division sign
{"\u00F8", "oslash"}, // ? - lowercase o, slash
{"\u00F9", "ugrave"}, // ? - lowercase u, grave accent
{"\u00FA", "uacute"}, // ? - lowercase u, acute accent
{"\u00FB", "ucirc"}, // ? - lowercase u, circumflex accent
{"\u00FC", "uuml"}, // ? - lowercase u, umlaut
{"\u00FD", "yacute"}, // ? - lowercase y, acute accent
{"\u00FE", "thorn"}, // ? - lowercase thorn, Icelandic
{"\u00FF", "yuml"}, // ? - lowercase y, umlaut
{"\u2013", "ndash"},
{"\u2018", "lsquo"},
{"\u2019", "rsquo"},
{"\u201D", "rdquo"},
{"\u201C", "ldquo"},
{"\u2014", "mdash"},
{"'", "apos"}, // the controversial (but who cares!) '
// stackoverflow.com/questions/2083754/why-shouldnt-apos-be-used-to-escape-single-quotes
};
private static final HashMap htmldecode_lookupMap;
static {
htmldecode_lookupMap = new HashMap();
for (final CharSequence[] seq : htmldecode_ESCAPES)
htmldecode_lookupMap.put(seq[1].toString(), seq[0]);
}
// tok should be the output of htmlcoarsetok
static List dropAllTags(List tok) {
List list = new ArrayList();
for (int i = 0; i < l(tok); i++) {
String t = tok.get(i);
if (odd(i) && t.startsWith("<")) {
list.set(list.size()-1, list.get(list.size()-1) + tok.get(i+1));
++i;
} else
list.add(t);
}
return list;
}
// alternatively, call this convenient function
static String dropAllTags(String html) {
return join(dropAllTags(htmlcoarsetok(html)));
}
static boolean isLocalSnippetID(String snippetID) {
return isSnippetID(snippetID) && isLocalSnippetID(psI(snippetID));
}
static boolean isLocalSnippetID(long snippetID) {
return snippetID >= 1000 && snippetID <= 9999;
}
static String loadLocalSnippet(String snippetID) {
return loadLocalSnippet(psI(snippetID));
}
static String loadLocalSnippet(long snippetID) {
return loadTextFile(localSnippetFile(snippetID));
}
static IResourceLoader vm_getResourceLoader() {
return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader"));
}
static String fsI(String id) {
return formatSnippetID(id);
}
static String fsI(long id) {
return formatSnippetID(id);
}
static String md5(String text) { try {
if (text == null) return "-";
return bytesToHex(md5_impl(toUtf8(text))); // maybe different than the way PHP does it...
} catch (Exception __e) { throw rethrow(__e); } }
static String md5(byte[] data) {
if (data == null) return "-";
return bytesToHex(md5_impl(data));
}
static byte[] md5_impl(byte[] data) { try {
return MessageDigest.getInstance("MD5").digest(data);
} catch (Exception __e) { throw rethrow(__e); } }
static String md5(File file) {
return md5OfFile(file);
}
static String tb_mainServer_default = "http://code.botcompany.de:8081";
static Object tb_mainServer_override; // func -> S
static String tb_mainServer() {
if (tb_mainServer_override != null) return (String) callF(tb_mainServer_override);
return trim(loadTextFile(tb_mainServer_file(),
tb_mainServer_default));
}
static File tb_mainServer_file() {
return getProgramFile("#1001638", "mainserver.txt");
}
static boolean tb_mainServer_isDefault() {
return eq(tb_mainServer(), tb_mainServer_default);
}
static String standardCredentials() {
String user = standardCredentialsUser();
String pass = standardCredentialsPass();
if (nempty(user) && nempty(pass))
return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass);
return "";
}
static String loadTextFile(String fileName) {
return loadTextFile(fileName, null);
}
static String loadTextFile(File f, String defaultContents) { try {
checkFileNotTooBigToRead(f);
if (f == null || !f.exists()) return defaultContents;
FileInputStream fileInputStream = new FileInputStream(f);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
return loadTextFile(inputStreamReader);
} catch (Exception __e) { throw rethrow(__e); } }
public static String loadTextFile(File fileName) {
return loadTextFile(fileName, null);
}
static String loadTextFile(String fileName, String defaultContents) {
return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents);
}
static String loadTextFile(Reader reader) throws IOException {
StringBuilder builder = new StringBuilder();
try {
char[] buffer = new char[1024];
int n;
while (-1 != (n = reader.read(buffer)))
builder.append(buffer, 0, n);
} finally {
reader.close();
}
return str(builder);
}
/** writes safely (to temp file, then rename) */
static File saveTextFile(String fileName, String contents) throws IOException {
CriticalAction action = beginCriticalAction("Saving file " + fileName + " (" + l(contents) + " chars)");
try {
File file = new File(fileName);
mkdirsForFile(file);
String tempFileName = fileName + "_temp";
File tempFile = new File(tempFileName);
if (contents != null) {
if (tempFile.exists()) try {
String saveName = tempFileName + ".saved." + now();
copyFile(tempFile, new File(saveName));
} catch (Throwable e) { printStackTrace(e); }
FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath());
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
printWriter.print(contents);
printWriter.close();
}
if (file.exists() && !file.delete())
throw new IOException("Can't delete " + fileName);
if (contents != null)
if (!tempFile.renameTo(file))
throw new IOException("Can't rename " + tempFile + " to " + file);
vmBus_send("wroteFile", file);
return file;
} finally {
action.done();
}
}
static File saveTextFile(File fileName, String contents) { try {
saveTextFile(fileName.getPath(), contents);
return fileName;
} catch (Exception __e) { throw rethrow(__e); } }
static File getGlobalCache() {
File file = new File(javaxCachesDir(), "Binary Snippets");
file.mkdirs();
return file;
}
static A setThreadLocal(ThreadLocal tl, A value) {
if (tl == null) return null;
A old = tl.get();
tl.set(value);
return old;
}
static int loadPage_defaultTimeout = 60000;
static ThreadLocal loadPage_charset = new ThreadLocal();
static boolean loadPage_allowGzip = true, loadPage_debug;
static boolean loadPage_anonymous = false; // don't send computer ID
static int loadPage_verboseness = 100000;
static int loadPage_retries = 1; //60; // seconds
static ThreadLocal loadPage_silent = new ThreadLocal();
static volatile int loadPage_forcedTimeout; // ms
static ThreadLocal loadPage_forcedTimeout_byThread = new ThreadLocal(); // ms
static ThreadLocal>> loadPage_responseHeaders = new ThreadLocal();
static ThreadLocal