Warning : session_start(): open(/var/lib/php/sessions/sess_i71b9cdis1qirsjfpqdo8rmdhl, 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 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.*;
public class main {
// A concept should be an object, not just a string.
static int concepts_internStringsLongerThan = 10;
static ThreadLocal concepts_unlisted = new ThreadLocal();
static interface Derefable {
Concept get();
}
static class Concepts {
Map concepts = synchroTreeMap();
HashMap perClassData = new HashMap();
String programID;
long idCounter;
volatile long changes = 1, changesWritten;
volatile java.util.Timer autoSaver;
volatile boolean savingConcepts;
int autoSaveInterval = 1000;
boolean useGZIP = true;
Concepts() {}
Concepts(String programID) {
this.programID = programID;}
synchronized long newID() {
do {
++idCounter;
} while (hasConcept(idCounter));
return idCounter;
}
void initProgramID() {
if (programID == null)
programID = programID();
}
Concepts load() {
initProgramID();
clearConcepts();
DynamicObject_loading = true;
try {
long time = now();
readLocally2(this, programID, "concepts");
assignConceptsToUs();
done("Loading concepts", time);
readLocally2(this, programID, "idCounter");
} finally {
DynamicObject_loading = false;
}
return this;
}
Concepts loadConcepts() { return load(); }
void assignConceptsToUs() {
for (Concept c : values(concepts)) {
c._concepts = this;
callOpt_noArgs(c, "_doneLoading2");
}
}
String progID() {
return programID == null ? programID() : programID;
}
Concept getConcept(String id) {
return empty(id) ? null : getConcept(parseLong(id));
}
Concept getConcept(long id) {
return (Concept) concepts.get((long) id);
}
Concept getConcept(PassRef ref) {
return ref == null ? null : getConcept(ref.longID());
}
boolean hasConcept(long id) {
return concepts.containsKey((long) id);
}
void deleteConcept(long id) {
Concept c = getConcept(id);
if (c == null)
print("Concept " + id + " not found");
else
c.delete();
}
// call in only one thread
void saveConceptsIfDirty() {
initProgramID();
savingConcepts = true;
long start = now();
try {
String s;
//synchronized(main.class) {
long _changes = changes;
if (_changes == changesWritten) return;
saveLocally2(this, programID, "idCounter");
s = structure(cloneMap(concepts));
changesWritten = _changes; // only update when structure didn't fail (e.g. because of ConcurrentModificationException)
//}
s = javaTokWordWrap(s);
long time = now()-start;
print("Saving " + l(s) + " chars (" /*+ changesWritten + ", "*/ + time + " ms)");
start = now();
File f = getProgramFile(useGZIP ? "concepts.structure.gz" : "concepts.structure");
if (useGZIP) {
saveGZTextFile(f, s);
getProgramFile("concepts.structure").delete();
} else {
saveTextFile(f, s);
getProgramFile("concepts.structure.gz").delete();
}
copyFile(f, getProgramFile("concepts.structure" + (useGZIP ? ".gz" : "") + ".backup" + ymd() + "-" + formatInt(hours(), 2)));
time = now()-start;
print("Saved " + toK(f.length()) + " K (" + time + " ms)");
} finally {
savingConcepts = false;
}
}
void saveConcepts() {
saveConceptsIfDirty();
}
void clearConcepts() {
concepts.clear();
change();
}
synchronized void change() {
++changes;
}
// auto-save every second if dirty
synchronized void autoSaveConcepts() {
if (autoSaver == null) {
autoSaver = doEvery(autoSaveInterval, new Runnable() { public void run() { try { saveConcepts();
} catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); } } });
print("Installed auto-saver (" + autoSaveInterval + " ms, " + progID() + ")");
}
}
void cleanMeUp() {
if (autoSaver != null) {
autoSaver.cancel();
autoSaver = null;
}
while (savingConcepts) sleep(10);
saveConceptsIfDirty();
}
Map getIDsAndNames() {
Map map = new HashMap();
Map cloned = cloneMap(concepts);
for (long id : keys(cloned))
map.put(id, cloned.get(id).className);
return map;
}
void deleteConcepts(List l) {
for (Object o : l)
if (o instanceof Long)
concepts.remove((Long) o);
else if (o instanceof Concept)
((Concept) o).delete();
else
warn("Can't delete " + getClassName(o));
}
A conceptOfType(Class type) {
return firstOfType(allConcepts(), type);
}
List conceptsOfType(Class type) {
return filterByType(allConcepts(), type);
}
List listConcepts(Class type) {
return conceptsOfType(type);
}
List list(Class type) {
return conceptsOfType(type);
}
List list(String type) {
return conceptsOfType(type);
}
List conceptsOfType(String type) {
return filterByDynamicType(allConcepts(), "main$" + type);
}
boolean hasConceptOfType(Class extends Concept> type) {
return hasType(allConcepts(), type);
}
void persistConcepts() {
loadConcepts();
autoSaveConcepts();
}
// We love synonyms
void conceptPersistence() {
persistConcepts();
}
void persist() { persistConcepts(); }
void persist(int interval) { autoSaveInterval = interval; persist(); }
// Runs r if there is no concept of that type
A ensureHas(Class c, Runnable r) {
A a = conceptOfType(c);
if (a == null) {
r.run();
a = conceptOfType(c);
if (a == null)
throw fail("Concept not made by " + r + ": " + shortClassName(c));
}
return a;
}
// Ensures that every concept of type c1 is ref'd by a concept of
// type c2.
// Type of func: voidfunc(concept)
void ensureHas(Class extends Concept> c1, Class extends Concept> c2, Object func) {
for (Concept a : conceptsOfType(c1)) {
Concept b = findBackRef(a, c2);
if (b == null) {
callF(func, a);
b = findBackRef(a, c2);
if (b == null)
throw fail("Concept not made by " + func + ": " + shortClassName(c2));
}
}
}
// Type of func: voidfunc(concept)
void forEvery(Class extends Concept> type, Object func) {
for (Concept c : conceptsOfType(type))
callF(func, c);
}
int deleteAll(Class extends Concept> type) {
List l = (List) conceptsOfType(type);
for (Concept c : l) c.delete();
return l(l);
}
Collection allConcepts() {
synchronized(concepts) {
return new ArrayList(values(concepts));
}
}
PassRef toPassRef(Concept c) {
return new PassRef(c);
}
int countConcepts(Class c, Object... params) {
int n = 0;
for (A x : list(c))
if (checkConceptFields(x, params))
++n;
return n;
}
int countConcepts() {
return l(concepts);
}
// inter-process methods
PassRef xnew(String name, Object... values) {
return new PassRef(cnew(name, values));
}
void xset(long id, String field, Object value) {
xset(new PassRef(id), field, value);
}
void xset(PassRef c, String field, Object value) {
if (value instanceof PassRef)
value = getConcept((PassRef) value);
cset(getConcept(c), field, value);
}
Object xget(long id, String field) {
return xget(new PassRef(id), field);
}
Object xget(PassRef c, String field) {
return cget(getConcept(c), field);
}
void xdelete(long id) {
xdelete(new PassRef(id));
}
void xdelete(PassRef c) {
getConcept(c).delete();
}
List xlist() {
return map("toPassRef", allConcepts());
}
List xlist(String className) {
return map("toPassRef", conceptsOfType(className));
}
}
static volatile Concepts mainConcepts = new Concepts(); // Where we create new concepts
static class Concept extends DynamicObject {
transient Concepts _concepts; // Where we belong
long id;
Object madeBy;
//double energy;
//bool defunct;
long created;
// used only internally (cnew)
Concept(String className) {
super(className);
_created();
}
Concept() {
if (!DynamicObject_loading) {
className = shortClassName(this);
//print("New concept of type " + className);
_created();
}
}
List[ refs = new ArrayList][();
List][ backRefs = new ArrayList][();
void _created() {
_concepts = mainConcepts;
id = _concepts.newID();
created = now();
_concepts.concepts.put((long) id, this);
_concepts.change();
}
void put(String field, Object value) {
fieldValues.put(field, value);
_concepts.change();
}
Object get(String field) {
return fieldValues.get(field);
}
class Ref] {
A value;
Ref() {
if (!DynamicObject_loading) refs.add(this);
}
Ref(A value) {
this.value = value;
refs.add(this);
index();
}
// get owning concept (source)
Concept concept() {
return Concept.this;
}
// get target
A get() {
return value;
}
void set(A a) {
if (a == value) return;
unindex();
value = a;
index();
}
void set(Ref ref) {
set(ref.get());
}
void index() {
if (value != null)
value.backRefs.add(this);
change();
}
void unindex() {
if (value != null)
value.backRefs.remove(this);
}
void change() {
Concept.this.change();
}
}
class RefL extends AbstractList {
List[> l = new ArrayList][>();
public A set(int i, A o) {
A prev = l.get(i).get();
l.get(i).set(o);
return prev;
}
public void add(int i, A o) {
l.add(i, new Ref(o));
}
public A get(int i) {
return l.get(i).get();
}
public A remove(int i) {
return l.remove(i).get();
}
public int size() {
return l.size();
}
}
void delete() {
//name = "[defunct " + name + "]";
//defunct = true;
//energy = 0;
for (Ref r : refs)
r.unindex();
refs.clear();
for (Ref r : cloneList(backRefs))
r.set((Concept) null);
backRefs.clear(); // Should be clear at this point anyway
if (_concepts != null) {
_concepts.concepts.remove((long) id);
change();
_concepts = null;
}
id = 0;
}
BaseXRef export() {
return new BaseXRef(_concepts.progID(), id);
}
// notice system of a change in this object
void change() {
if (_concepts != null) _concepts.change();
}
String _programID() {
return _concepts == null ? programID() : _concepts.progID();
}
} // class Concept
// for inter-process communication
// prepared for string ids if we do them later
static class PassRef {
String id;
PassRef() {} // make serialisation happy
PassRef(long id) { this.id = str(id); }
PassRef(Concept c) { this(c.id); }
long longID() { return parseLong(id); }
public String toString() {
return id;
}
}
static class Event extends Concept {}
// Reference to a concept in another program
static class BaseXRef {
String programID;
long id;
BaseXRef() {}
BaseXRef(String programID, long id) {
this.id = id;
this.programID = programID;}
public boolean equals(Object o) {
if (!(o instanceof BaseXRef)) return false;
BaseXRef r = (BaseXRef) ( o);
return eq(programID, r.programID) && eq(id, r.id);
}
public int hashCode() {
return programID.hashCode() + (int) id;
}
}
// BaseXRef as a concept
static class XRef extends Concept {
BaseXRef ref;
XRef() {}
XRef(BaseXRef ref) {
this.ref = ref; _doneLoading2(); }
// after we have been added to concepts
void _doneLoading2() {
getIndex().put(ref, this);
}
HashMap] getIndex() {
return getXRefIndex(_concepts);
}
}
static synchronized HashMap getXRefIndex(Concepts concepts) {
HashMap cache = (HashMap) concepts.perClassData.get(XRef.class);
if (cache == null)
concepts.perClassData.put(XRef.class, cache = new HashMap());
return cache;
}
// uses mainConcepts
static XRef lookupOrCreateXRef(BaseXRef ref) {
XRef xref = getXRefIndex(mainConcepts).get(ref);
if (xref == null)
xref = new XRef(ref);
return xref;
}
// define standard concept functions to use main concepts
static List list(Class type) {
return mainConcepts.list(type);
}
static List list(String type) {
return mainConcepts.list(type);
}
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 A cnew(Class cc, Object... values) {
A c = nuObject(cc);
csetAll(c, values);
return c;
}
static Object cget(Concept c, String field) {
Object o = getOpt(c, field);
if (o instanceof Concept.Ref) return ((Concept.Ref) o).get();
return o;
}
static void csetAll(Concept c, Object... values) {
cset(c, values);
}
static void cset(Concept c, Object... values) { try {
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 PassRef) value = c._concepts.getConcept((PassRef) value);
value = deref(value);
if (value instanceof String && l((String) value) >= concepts_internStringsLongerThan) value = ((String) value).intern();
if (f == null)
c.fieldValues.put(field, value instanceof Concept ? c.new Ref((Concept) value) : value);
else if (isSubtypeOf(f.getType(), Concept.Ref.class))
((Concept.Ref) f.get(c)).set((Concept) value);
else
f.set(c, value);
}
c.change();
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static int countConcepts(Class c, Object... params) {
return mainConcepts.countConcepts(c, params);
}
static int countConcepts() {
return mainConcepts.countConcepts();
}
static A findBackRef(Concept c, Class type) {
for (Concept.Ref r : c.backRefs)
if (instanceOf(r.concept(), type))
return (A) r.concept(); return null;
}
static List findBackRefs(Collection extends Concept> concepts, Class type) {
IdentityHashMap l = new IdentityHashMap ();
for (Concept c : concepts)
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 ();
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 void cleanMeUp() {
mainConcepts.cleanMeUp();
}
static Concept getConcept(long id) {
return mainConcepts.getConcept(id);
}
static void loadAndAutoSaveConcepts() {
mainConcepts.persist();
}
static void loadConceptsFrom(String progID) {
mainConcepts.programID = progID;
mainConcepts.load();
}
static List conceptsOfType(String type) {
return mainConcepts.conceptsOfType(type);
}
static Collection allConcepts() {
return mainConcepts.allConcepts();
}
static long changeCount() {
return mainConcepts.changes;
}
// 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 void deleteConcepts(List l) {
mainConcepts.deleteConcepts(l);
}
static int deleteAll(Class extends Concept> type) {
return mainConcepts.deleteAll(type);
}
// Dynamic Concepts
static class Screenshot extends Concept {
String pngPath; // optional, relative (program ID + "/" + file name)
Rect r; // optional, rectangle that was shot
Screenshot() {} // for persistance
Screenshot(BufferedImage img) {
savePNG(pngFile(), img);
}
File pngFile() {
if (pngPath != null)
return prepareFile(new File(javaxDataDir(), pngPath));
return prepareProgramFile(_programID(), "screenshot" + id + ".png");
}
BufferedImage loadImage() {
return loadImage2(pngFile());
}
boolean hasImage() {
return pngFile().exists();
}
}
static class TransientScreenshot extends Screenshot {
transient BufferedImage img;
TransientScreenshot() {} // for persistance
TransientScreenshot(BufferedImage img) {
this.img = img;}
boolean hasImage() { return img != null; }
BufferedImage loadImage() { return img; }
void disposeImage() { img = null; }
}
static class MarkedClip extends Clip {
static String _fieldOrder = "screenshot positionInScreenshot";
Ref screenshot = new Ref();
Rect positionInScreenshot;
}
static class Clip extends Concept {
static String _fieldOrder = "originalID img description";
long originalID; // ID in #1005389
BWImage img;
String description;
}
static class Found extends Concept {
static String _fieldOrder = "screenshot clip fi";
Ref screenshot = new Ref();
Ref clip = new Ref();
FoundImg fi; // contains Rect r
}
static class FullySearched extends Concept {
static String _fieldOrder = "screenshot clip";
Ref screenshot = new Ref();
Ref clip = new Ref();
} // PIF Classes v2
static String src1 = "#1005715", src2 = "#1005721";
static int maxTotal = 10;
static Map, MultiSet> correlations = new HashMap();
public static void main(String[] args) throws Exception {
Concepts in1 = new Concepts(src1).load();
Concepts in2 = new Concepts(src2).load();
in1.deleteAll(Found.class);
in2.deleteAll(Found.class);
print("Loaded from:");
printIndent(joinLines(snippetsWithTitles(ll(src1, src2))));
print("Total concepts: " + in1.countConcepts() + ", " + in2.countConcepts());
List clips1 = goodClips(in1), clips2 = goodClips(in2);
print("Good clips: " + l(clips1) + ", " + l(clips2));
while (licensed()) {
TransientScreenshot t = new TransientScreenshot(shootScreen2());
ImageFinder finder = new ImageFinder(t, concatLists(clips1, clips2));
finder.maxTotal = maxTotal;
finder.run();
List found1 = findBackRefs(clips1, Found.class);
List found2 = findBackRefs(clips2, Found.class);
deleteAll(Found.class);
print("#found = " + l(found1) + " / " + l(found2));
printFound(found1);
print();
printFound(found2);
print();
for (Found a : found1)
for (Found b : found2)
correlate(correlations, a, b);
for (Pair key : correlations.keySet()) {
print(key.a.id + " / " + key.b.id + " => " + struct(correlations.get(key)));
}
sleepSeconds(5);
}
}
static void correlate(Map, MultiSet> correlations, Found a, Found b) {
Pair key = new Pair(a.clip.get(), b.clip.get());
Pt p = new Pt(b.fi.r.x-a.fi.r.x, b.fi.r.y-a.fi.r.y);
MultiSet ms = correlations.get(key);
if (ms == null)
correlations.put(key, ms = new MultiSet());
ms.add(p);
}
static void printFound(List l) {
for (Found f : l)
print(f.fi.r + " " + f.clip.get().id);
}
static List goodClips(Concepts in) {
return filter(in.list(Clip.class) , new Object() { Object get(Clip c) { return !swic(c.description, "bad") ; }
public String toString() { return "!swic(c.description, \"bad\")"; }});
}
static List ll(A... a) {
return litlist(a);
}
static String struct(Object o) {
return structure(o);
}
static String formatInt(int i, int digits) {
return padLeft(str(i), '0', digits);
}
static File prepareProgramFile(String name) {
return mkdirsForFile(getProgramFile(name));
}
static File prepareProgramFile(String progID, String name) {
return mkdirsForFile(getProgramFile(progID, name));
}
static Object callF(Object f, Object... args) {
return callFunction(f, args);
}
static String joinLines(List lines) {
return fromLines(lines);
}
static String joinLines(String glue, String text) {
return join(glue, toLines(text));
}
// firstDelay = delay
static java.util.Timer doEvery(int delay, Runnable r) {
java.util.Timer timer = new java.util.Timer();
timer.scheduleAtFixedRate(timerTask(r), delay, delay);
return timer;
}
static ArrayList asList(A[] a) {
return new ArrayList (Arrays.asList(a));
}
static ArrayList asList(int[] a) {
ArrayList l = new ArrayList();
for (int 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 void printIndent(Object o) {
print(indentx(str(o)));
}
static void printIndent(String indent, Object o) {
print(indentx(indent, str(o)));
}
static void printIndent(int indent, Object o) {
print(indentx(indent, str(o)));
}
static boolean empty(Collection c) {
return isEmpty(c);
}
static boolean empty(String s) {
return isEmpty(s);
}
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);
throw fail("unknown type for 'empty': " + getType(o));
}
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 RGBImage loadImage(String snippetIDOrURL) {
return new RGBImage(loadBufferedImage(snippetIDOrURL));
}
static WeakHashMap> callOpt_noArgs_cache = new WeakHashMap();
static Object callOpt_noArgs(Object o, String method) { try {
if (o == null) return null;
if (o instanceof Class)
return callOpt(o, method); // not optimized
Class c = o.getClass();
HashMap map;
synchronized(callOpt_noArgs_cache) {
map = callOpt_noArgs_cache.get(c);
if (map == null)
map = callOpt_noArgs_makeCache(c);
}
Method m = map.get(method);
return m != null ? m.invoke(o) : null;
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
// used internally - we are in synchronized block
static HashMap callOpt_noArgs_makeCache(Class c) {
HashMap map = new HashMap();
Class _c = c;
do {
for (Method m : c.getDeclaredMethods())
if (m.getParameterTypes().length == 0) {
m.setAccessible(true);
String name = m.getName();
if (!map.containsKey(name))
map.put(name, m);
}
_c = _c.getSuperclass();
} while (_c != null);
callOpt_noArgs_cache.put(c, map);
return map;
}
static BufferedImage loadImage2(String snippetIDOrURL) {
return loadBufferedImage(snippetIDOrURL);
}
static BufferedImage loadImage2(File file) {
return loadBufferedImage(file);
}
static File prepareFile(File file) {
return mkdirsForFile(file);
}
static List filterByDynamicType(Collection c, String type) {
List l = new ArrayList ();
for (A x : c)
if (eq(dynamicClassName(x), type))
l.add(x);
return l;
}
static List filterByType(Collection c, Class type) {
List l = new ArrayList ();
for (Object x : c)
if (isInstanceX(type, x))
l.add((A) x);
return l;
}
static List cloneList(Collection l) {
//O mutex = getOpt(l, "mutex");
/*if (mutex != null)
synchronized(mutex) {
ret new ArrayList (l);
}
else
ret new ArrayList (l);*/
// assume mutex is equal to collection, which will be true unless you explicitly pass a mutex to synchronizedList() which no one ever does.
synchronized(l) {
return new ArrayList (l);
}
}
static HashMap findClass_cache = new HashMap();
// currently finds only inner classes of class "main"
// returns null on not found
// this is the simple version that is not case-tolerant
static Class findClass(String name) {
synchronized(findClass_cache) {
if (findClass_cache.containsKey(name))
return findClass_cache.get(name);
if (!isJavaIdentifier(name)) return null;
Class c;
try {
c = Class.forName("main$" + name);
} catch (ClassNotFoundException e) {
c = null;
}
findClass_cache.put(name, c);
return c;
}
}
static boolean eq(Object a, Object b) {
if (a == null) return b == null;
if (a.equals(b)) return true;
if (a instanceof BigInteger) {
if (b instanceof Integer) return a.equals(BigInteger.valueOf((Integer) b));
if (b instanceof Long) return a.equals(BigInteger.valueOf((Long) b));
}
return false;
}
static int done_minPrint = 10;
static long done(long startTime, String desc) {
long time = now()-startTime;
if (time >= done_minPrint)
print(desc + " [" + time + " ms]");
return time;
}
static long done(String desc, long startTime) {
return done(startTime, desc);
}
static long done(long startTime) {
return done(startTime, "");
}
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;
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;
}
return;
}
Field f = map.get(field);
if (f != null)
smartSet(f, o, value); // possible improvement: skip setAccessible
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__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() & Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static List snippetsWithTitles(List ids) {
final Map map = getSnippetTitles(ids);
return map(new Object() { Object get(String id) { return fsI(id) + " - " + map.get(fsI(id)) ; }
public String toString() { return "fsI(id) + \" - \" + map.get(fsI(id))"; }}, ids);
}
static String snippetsWithTitles(String... ids) {
return join(", ", snippetsWithTitles(asList(ids)));
}
static String str(Object o) {
return String.valueOf(o);
}
static boolean isSubtypeOf(Class a, Class b) {
return b.isAssignableFrom(a); // << always hated that method, let's replace it!
}
static long toK(long l) {
return (l+1023)/1024;
}
static boolean warn_on = true;
static void warn(String s) {
if (warn_on)
print("Warning: " + s);
}
static void warn(String s, List warnings) {
warn(s);
if (warnings != null)
warnings.add(s);
}
static RuntimeException fail() {
throw new RuntimeException("fail");
}
static RuntimeException fail(Object msg) {
throw new RuntimeException(String.valueOf(msg));
}
static RuntimeException fail(String msg) {
throw new RuntimeException(unnull(msg));
}
// disabled for now to shorten some programs
/*static RuntimeException fail(S msg, O... args) {
throw new RuntimeException(format(msg, args));
}*/
static List concatLists(List ... lists) {
List l = new ArrayList ();
for (List list : lists)
if (list != null)
l.addAll(list);
return l;
}
static List concatLists(Collection> lists) {
List l = new ArrayList ();
for (List list : lists)
if (list != null)
l.addAll(list);
return l;
}
/** writes safely (to temp file, then rename) */
public static void saveTextFile(String fileName, String contents) throws IOException {
File file = new File(fileName);
File parentFile = file.getParentFile();
if (parentFile != null)
parentFile.mkdirs();
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);
}
public static void saveTextFile(File fileName, String contents) {
try {
saveTextFile(fileName.getPath(), contents);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static Object nuObject(String className, Object... args) { try {
return nuObject(Class.forName(className), args);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
// too ambiguous - maybe need to fix some callers
/*static O nuObject(O realm, S className, O... args) {
ret nuObject(_getClass(realm, className), args);
}*/
static A nuObject(Class c, Object... args) { try {
Constructor m = nuObject_findConstructor(c, args);
m.setAccessible(true);
return (A) m.newInstance(args);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static Constructor nuObject_findConstructor(Class c, Object... args) {
for (Constructor m : c.getDeclaredConstructors()) {
if (!nuObject_checkArgs(m.getParameterTypes(), args, false))
continue;
return m;
}
throw new RuntimeException("Constructor with " + args.length + " matching parameter(s) not found in " + c.getName());
}
static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) {
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
static void readLocally(String progID, String varNames) {
readLocally2(mc(), progID, varNames);
}
static void readLocally(String varNames) {
readLocally2(mc(), programID(), varNames);
}
static void readLocally2(Object obj, String varNames) {
readLocally2(obj, programID(), varNames);
}
// read a string variable from standard storage
// does not overwrite variable contents if there is no file
static synchronized void readLocally2(Object obj, String progID, String varNames) {
for (String variableName : codeTokensOnly(javaTok(varNames))) {
File textFile = new File(programDir(progID), variableName + ".text");
String value = loadTextFile(textFile);
if (value != null)
set(main.class, variableName, value);
else {
File structureFile = new File(programDir(progID), variableName + ".structure");
value = loadTextFile(structureFile);
if (value == null) {
File structureGZFile = new File(programDir(progID), variableName + ".structure.gz");
value = loadGZTextFile(structureGZFile);
}
if (value != null)
readLocally_set(obj, variableName, unstructure(value));
}
}
}
static void readLocally_set(Object c, String varName, Object value) {
Object oldValue = get(c, varName);
if (oldValue instanceof List && !(oldValue instanceof ArrayList) && value != null) {
// Assume it's a synchroList.
value = synchroList((List) value);
}
set(c, varName, value);
}
static String getClassName(Object o) {
return o == null ? "null" : o.getClass().getName();
}
static String javaTokWordWrap(String s) {
int cols = 120, col = 0;
List tok = javaTok(s);
for (int i = 0; i < l(tok); i++) {
String t = tok.get(i);
if (odd(i) && col >= cols && !containsNewLine(t))
tok.set(i, t += "\n");
int idx = t.lastIndexOf('\n');
if (idx >= 0) col = l(t)-(idx+1);
else col += l(t);
}
return join(tok);
}
public static void copyFile(File src, File dest) { try {
mkdirsForFile(dest);
FileInputStream inputStream = new FileInputStream(src.getPath());
FileOutputStream outputStream = newFileOutputStream(dest.getPath());
try {
copyStream(inputStream, outputStream);
inputStream.close();
} finally {
outputStream.close();
}
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static Object deref(Object o) {
if (o instanceof Derefable) o = ((Derefable) o).get();
return o;
}
static void sleepSeconds(double s) {
if (s > 0) sleep(round(s*1000));
}
static File javaxDataDir_dir; // can be set to work on different base dir
static File javaxDataDir() {
return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data");
}
static Set keys(Map map) {
return map.keySet();
}
static Set keys(Object map) {
return keys((Map) map);
}
static Collection values(Map map) {
return map == null ? emptyList() : map.values();
}
static A firstOfType(Collection c, Class type) {
for (Object x : c)
if (isInstanceX(type, x))
return (A) x;
return null;
}
static Str concept(String name) {
for (Str s : list(Str.class))
if (eqic(s.name, name) || containsIgnoreCase(s.otherNames, name))
return s;
return new Str(name);
}
static boolean swic(String a, String b) {
return startsWithIgnoreCase(a, b);
}
static void warnIfOddCount(Object... list) {
if (odd(l(list)))
warn("Odd list size: " + struct(list));
}
static void saveGZTextFile(File file, String contents) { try {
File parentFile = file.getParentFile();
if (parentFile != null)
parentFile.mkdirs();
String tempFileName = file.getPath() + "_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());
GZIPOutputStream gos = new GZIPOutputStream(fileOutputStream);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(gos, "UTF-8");
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
printWriter.print(contents);
printWriter.close();
gos.close();
fileOutputStream.close();
}
if (file.exists() && !file.delete())
throw new IOException("Can't delete " + file.getPath());
if (contents != null)
if (!tempFile.renameTo(file))
throw new IOException("Can't rename " + tempFile + " to " + file);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static void savePNG(BufferedImage img, File file) { try {
ImageIO.write(img, "png", mkdirsFor(file));
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
// gotta love convenience & program-smartness
static void savePNG(File file, BufferedImage img) {
savePNG(img, file);
}
static Map synchroTreeMap() {
return Collections.synchronizedMap(new TreeMap());
}
static void sleep(long ms) {
ping();
try {
Thread.sleep(ms);
} catch (Exception e) { throw new RuntimeException(e); }
}
static void sleep() { try {
print("Sleeping.");
synchronized(main.class) { main.class.wait(); }
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String ymd() {
return year() + formatInt(month(), 2) + formatInt(dayOfMonth(), 2);
}
static void load(String varName) {
readLocally(varName);
}
static void load(String progID, String varName) {
readLocally(progID, varName);
}
// get purpose 1: access a list/array (safer version of x.get(y))
static A get(List l, int idx) {
return idx >= 0 && idx < l(l) ? l.get(idx) : 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;
}
static Class get_dynamicObject = DynamicObject.class;
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
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 (get_dynamicObject != null && get_dynamicObject.isInstance(o))
return call(get_raw(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() & 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 long now_virtualTime;
static long now() {
return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis();
}
static Object[] expandParams(Class c, Object[] params) {
if (l(params) == 1)
params = new Object[] { singleFieldName(c), params[0] };
else
warnIfOddCount(params);
return params;
}
static String shortClassName(Object o) {
if (o == null) return null;
Class c = o instanceof Class ? (Class) o : o.getClass();
String name = c.getName();
return shortenClassName(name);
}
static boolean checkConceptFields(Concept x, Object... data) {
for (int i = 0; i < l(data); i += 2)
if (neq(cget(x, (String) data[i]), deref(data[i+1])))
return false;
return true;
}
static List map(Iterable l, Object f) {
return map(f, l);
}
static List map(Object f, Iterable l) {
List x = new ArrayList();
Object mc = mc();
for (Object o : unnull(l))
x.add(callFunction(f, o));
return x;
}
static List map(Object f, Object[] l) {
return map(f, asList(l));
}
static List map(Map map, Object f) {
List x = new ArrayList();
for (Object _e : map.entrySet()) {
Map.Entry e = (Map.Entry) _e;
x.add(callFunction(f, e.getKey(), e.getValue()));
}
return x;
}
static String programID() {
return getProgramID();
}
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 void saveLocally(String variableName) {
saveLocally(programID(), variableName);
}
static void saveLocally(String progID, String variableName) {
saveLocally2(mc(), progID, variableName);
}
static void saveLocally2(Object obj, String variableName) {
saveLocally2(obj, programID(), variableName);
}
static synchronized void saveLocally2(Object obj, String progID, String variableName) {
File textFile = new File(programDir(progID), variableName + ".text");
File structureFile = new File(programDir(progID), variableName + ".structure");
Object x = get(obj, variableName);
if (x == null) {
textFile.delete();
structureFile.delete();
} else if (x instanceof String) {
saveTextFile(textFile, (String) x);
structureFile.delete();
} else {
saveTextFile(structureFile, structure(x));
textFile.delete();
}
}
static int hours() {
return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
}
static Map cloneMap(Map map) {
if (map == null) return litmap();
// assume mutex is equal to collection, which will be true unless you explicitly pass a mutex to synchronizedList() which no one ever does.
synchronized(map) {
return new HashMap(map);
}
}
static void set(Object o, String field, Object value) {
if (o instanceof Class) set((Class) o, field, value);
else try {
Field f = set_findField(o.getClass(), field);
smartSet(f, o, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static void set(Class c, String field, Object value) {
try {
Field f = set_findStaticField(c, field);
smartSet(f, null, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field set_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field set_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 BufferedImage shootScreen2() {
return shootScreen2(screenRectangle());
}
static BufferedImage shootScreen2(Rectangle area) { try {
return new Robot().createScreenCapture(area);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
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(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] 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 int l(Object o) {
return l((List) o); // incomplete
}
static boolean structure_showTiming, structure_checkTokenCount;
static String structure(Object o) {
structure_Data d = new structure_Data();
structure_1(o, d);
while (nempty(d.stack))
popLast(d.stack).run();
String s = str(d.out);
if (structure_checkTokenCount) {
print("token count=" + d.n);
assertEquals("token count", l(javaTokC(s)), d.n);
}
return s;
}
// leave to false, unless unstructure() breaks
static boolean structure_allowShortening = false;
static int structure_shareStringsLongerThan = 20;
static class structure_Data {
StringBuilder out = new StringBuilder();
int stringSizeLimit;
IdentityHashMap seen = new IdentityHashMap();
BitSet refd = new BitSet();
HashMap strings = new HashMap();
HashSet concepts = new HashSet();
HashMap> fieldsByClass = new HashMap();
Class conceptClass = findClass("Concept");
int n; // token count
List stack = new ArrayList();
// append single token
structure_Data append(String token) { out.append(token); ++n; return this; }
structure_Data append(int i) { out.append(i); ++n; return this; }
// append multiple tokens
structure_Data append(String token, int tokCount) { out.append(token); n += tokCount; return this; }
// extend last token
structure_Data app(String token) { out.append(token); return this; }
structure_Data app(int i) { out.append(i); return this; }
}
static void structure_1(Object o, final structure_Data d) {
final StringBuilder out = d.out;
if (o == null) { d.append("null"); return; }
Class c = o.getClass();
String name = c.getName();
String dynName = shortDynamicClassName(o);
boolean concept = d.conceptClass != null && d.conceptClass.isInstance(o);
List lFields = d.fieldsByClass.get(c);
if (lFields == null) {
// these are never back-referenced (for readability)
if (o instanceof Number) {
if (o instanceof Integer) { out.append(((Integer) o).intValue()); d.n++; return; }
if (o instanceof Long) { out.append(((Long) o).longValue()).append("L"); d.n++; return; }
if (o instanceof Float) { d.append("fl ", 2); quote_impl(str(o), out); return; }
if (o instanceof Double) { d.append("d(", 3); quote_impl(str(o), out); d.append(")"); return; }
if (o instanceof BigInteger) { out.append("bigint(").append(o).append(")"); d.n += 4; return; }
}
if (o instanceof Boolean) {
d.append(((Boolean) o).booleanValue() ? "t" : "f"); return;
}
if (o instanceof Character) {
d.append(quoteCharacter((Character) o)); return;
}
if (o instanceof File) {
d.append("File ").append(quote(((File) o).getPath())); return;
}
// referencable objects follow
Integer ref = d.seen.get(o);
if (o instanceof String && ref == null)
ref = d.strings.get((String) o);
if (ref != null) {
d.refd.set(ref);
d.append("t").app(ref); return;
}
ref = d.n; //d.seen.size()+1;
d.seen.put(o, ref);
//d.append("m").app(ref).app(" "); // marker
if (o instanceof String) {
String s = d.stringSizeLimit != 0 ? shorten((String) o, d.stringSizeLimit) : (String) o;
if (l(s) >= structure_shareStringsLongerThan)
d.strings.put(s, ref);
quote_impl(s, out); d.n++; return;
}
if (o instanceof HashSet) {
d.append("hashset ");
structure_1(new ArrayList((Set) o), d);
return;
}
if (o instanceof TreeSet) {
d.append("treeset ");
structure_1(new ArrayList((Set) o), d);
return;
}
if (o instanceof Collection && neq(name, "main$Concept$RefL")) {
d.append("[");
final int l = out.length();
final Iterator it = ((Collection) o).iterator();
d.stack.add(new Runnable() { public void run() { try {
if (!it.hasNext())
d.append("]");
else {
d.stack.add(this);
if (out.length() != l) d.append(", ");
structure_1(it.next(), d);
}
} catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); } } });
return;
}
if (o instanceof Map) {
if (o instanceof HashMap) d.append("hm");
d.append("{");
final int l = out.length();
final Iterator it = ((Map) o).entrySet().iterator();
d.stack.add(new Runnable() {
boolean v;
Map.Entry e;
public void run() {
if (v) {
d.append("=");
v = false;
d.stack.add(this);
structure_1(e.getValue(), d);
} else {
if (!it.hasNext())
d.append("}");
else {
e = (Map.Entry) it.next();
v = true;
d.stack.add(this);
if (out.length() != l) d.append(", ");
structure_1(e.getKey(), d);
}
}
}
});
return;
}
if (c.isArray()) {
if (o instanceof byte[]) {
d.append("ba ").append(quote(bytesToHex((byte[]) o))); return;
}
int n = Array.getLength(o);
if (o instanceof boolean[]) {
String hex = boolArrayToHex((boolean[]) o);
int i = l(hex);
while (i > 0 && hex.charAt(i-1) == '0' && hex.charAt(i-2) == '0') i -= 2;
d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); return;
}
String atype = "array", sep = ", ";
if (o instanceof int[]) {
//ret "intarray " + quote(intArrayToHex((int[]) o));
atype = "intarray";
sep = " ";
}
d.append(atype).append("{");
for (int i = 0; i < n; i++) {
if (i != 0) d.append(sep);
structure_1(Array.get(o, i), d);
}
d.append("}"); return;
}
if (o instanceof Class) {
d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); return;
}
if (o instanceof Throwable) {
d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); return;
}
if (o instanceof BitSet) {
BitSet bs = (BitSet) o;
d.append("bitset{", 2);
int l = out.length();
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
if (out.length() != l) d.append(", ");
d.append(i);
}
d.append("}"); return;
}
// Need more cases? This should cover all library classes...
if (name.startsWith("java.") || name.startsWith("javax.")) {
d.append("j ").append(quote(str(o))); return; // Hm. this is not unstructure-able
}
/*if (name.equals("main$Lisp")) {
fail("lisp not supported right now");
}*/
if (concept && !d.concepts.contains(dynName)) {
d.concepts.add(dynName);
d.append("c ");
}
// serialize an object with fields.
// first, collect all fields and values in fv.
TreeSet fields = new TreeSet(new Comparator() {
public int compare(Field a, Field b) {
return stdcompare(a.getName(), b.getName());
}
});
while (c != Object.class) {
for (Field field : getDeclaredFields_cached(c)) {
if ((field.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0)
continue;
String fieldName = field.getName();
fields.add(field);
// put special cases here...
}
c = c.getSuperclass();
}
lFields = asList(fields);
// Render this$1 first because unstructure needs it for constructor call.
for (int i = 0; i < l(lFields); i++) {
Field f = lFields.get(i);
if (f.getName().equals("this$1")) {
lFields.remove(i);
lFields.add(0, f);
break;
}
}
d.fieldsByClass.put(c, lFields);
}
LinkedHashMap fv = new LinkedHashMap();
for (Field f : lFields) {
Object value;
try {
value = f.get(o);
} catch (Exception e) {
value = "?";
}
if (value != null)
fv.put(f.getName(), value);
}
String shortName = dropPrefix("main$", name);
// Now we have fields & values. Process fieldValues if it's a DynamicObject.
// omit field "className" if equal to class's name
if (concept && eq(fv.get("className"), shortName))
fv.remove("className");
if (o instanceof DynamicObject) {
fv.putAll((Map) fv.get("fieldValues"));
fv.remove("fieldValues");
shortName = dynName;
fv.remove("className");
}
String singleField = fv.size() == 1 ? first(fv.keySet()) : null;
d.append(shortName);
final int l = out.length();
final Iterator it = fv.entrySet().iterator();
d.stack.add(new Runnable() { public void run() { try {
if (!it.hasNext()) {
if (out.length() != l)
d.append(")");
} else {
Map.Entry e = (Map.Entry) it.next();
d.append(out.length() == l ? "(" : ", ");
d.append((String) e.getKey()).append("=");
d.stack.add(this);
structure_1(e.getValue(), d);
}
} catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); } } });
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile StringBuffer 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 int print_maxLineLength = 0; // 0 = unset
static boolean print_silent; // total mute if set
static void print() {
print("");
}
// slightly overblown signature to return original object...
static A print(A o) {
ping();
if (print_silent) return o;
String s = String.valueOf(o) + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
// TODO if (print_maxLineLength != 0)
StringBuffer loc = local_log;
StringBuffer 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(long l) {
print(String.valueOf(l));
}
static void print(char c) {
print(String.valueOf(c));
}
static void print_append(StringBuffer buf, String s, int max) {
synchronized(buf) {
buf.append(s);
max /= 2;
if (buf.length() > max) try {
int newLength = max/2;
int ofs = buf.length()-newLength;
String newString = buf.substring(ofs);
buf.setLength(0);
buf.append("[...] ").append(newString);
} catch (Exception e) {
buf.setLength(0);
}
}
}
static Object getOpt(Object o, String field) {
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 new RuntimeException(e);
}
}
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 new RuntimeException(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() & Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static Field getOpt_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);
return null;
}
static long parseLong(String s) {
if (s == null) return 0;
return Long.parseLong(dropSuffix("L", s));
}
static long parseLong(Object s) {
return Long.parseLong((String) s);
}
static boolean equals(Object a, Object b) {
return a == null ? b == null : a.equals(b);
}
static boolean hasType(Collection c, Class type) {
for (Object x : c)
if (isInstanceX(type, x))
return true;
return false;
}
static int year() {
return Calendar.getInstance().get(Calendar.YEAR);
}
static Object callFunction(Object f, Object... args) {
if (f == null) return null;
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
} else if (f instanceof String)
return call(mc(), (String) f, args);
else
return call(f, "get", args);
//else throw fail("Can't call a " + getClassName(f));
}
static Map getSnippetTitles(List ids) { try {
return trimValues(transformKeys(jsonDecodeMap(loadPageSilently(new URL("http://tinybrain.de:8080/tb-int/get-titles.php?ids=" + urlencode(join(" ", parseSnippetIDs(ids))) + standardCredentials()))), new Object() { Object get(String id) { return fsI(id) ; }
public String toString() { return "fsI(id)"; }}));
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
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();
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
out.append(c);
}
out.append('"');
}
static String shorten(String s, int max) {
if (s == null) return "";
if (max < 0) return s;
return s.length() <= max ? s : s.substring(0, Math.min(s.length(), max)) + "...";
}
static String quoteCharacter(char c) {
if (c == '\'') return "'\\''";
if (c == '\\') return "'\\\\'";
return "'" + c + "'";
}
public static String join(String glue, Iterable strings) {
StringBuilder buf = new StringBuilder();
Iterator i = strings.iterator();
if (i.hasNext()) {
buf.append(i.next());
while (i.hasNext())
buf.append(glue).append(i.next());
}
return buf.toString();
}
public static String join(String glue, String[] strings) {
return join(glue, Arrays.asList(strings));
}
public static String join(Iterable strings) {
return join("", strings);
}
public static String join(String[] strings) {
return join("", strings);
}
static String fsI(String id) {
return formatSnippetID(id);
}
static String fsI(long id) {
return formatSnippetID(id);
}
static String shortDynamicClassName(Object o) {
if (o instanceof DynamicObject && ((DynamicObject) o).className != null)
return ((DynamicObject) o).className;
return shortClassName(o);
}
static String dropPrefix(String prefix, String s) {
return s.startsWith(prefix) ? s.substring(l(prefix)) : s;
}
static void printStackTrace(Throwable e) {
// we go to system.out now - system.err is nonsense
print(getStackTrace(e));
}
static void printStackTrace() {
printStackTrace(new Throwable());
}
static void printStackTrace(String indent, Throwable e) {
if (endsWithLetter(indent)) indent += " ";
printIndent(indent, getStackTrace(e));
}
static List codeTokensOnly(List tok) {
List l = new ArrayList();
for (int i = 1; i < tok.size(); i += 2)
l.add(tok.get(i));
return l;
}
static Map litmap(Object... x) {
TreeMap map = new TreeMap();
litmap_impl(map, x);
return map;
}
static void litmap_impl(Map map, Object... x) {
for (int i = 0; i < x.length-1; i += 2)
if (x[i+1] != null)
map.put(x[i], x[i+1]);
}
static boolean odd(int i) {
return (i & 1) != 0;
}
static String shortenClassName(String name) {
return name == null ? null : substring(name, xIndexOf(name, '$')+1);
}
static String getType(Object o) {
return getClassName(o);
}
static int dayOfMonth() {
return days();
}
static boolean isJavaIdentifier(String s) {
if (s.length() == 0 || !Character.isJavaIdentifierStart(s.charAt(0)))
return false;
for (int i = 1; i < s.length(); i++)
if (!Character.isJavaIdentifierPart(s.charAt(i)))
return false;
return true;
}
static TimerTask timerTask(final Runnable r) {
return new TimerTask() {
public void run() {
try { /* pcall 1*/
r.run();
/* pcall 2 */ } catch (Throwable __e) { printStackTrace(__e); }
}
};
}
static volatile boolean ping_pauseAll;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions;
static Map ping_actions = synchroMap(new WeakHashMap());
// returns true if it did anything
static boolean ping() { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) {
Object action;
synchronized(mc()) {
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 (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String programID;
static String getProgramID() {
return nempty(programID) ? formatSnippetID(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 String unnull(String s) {
return s == null ? "" : s;
}
static List unnull(List l) {
return l == null ? emptyList() : l;
}
static Iterable unnull(Iterable i) {
return i == null ? emptyList() : i;
}
static Object[] unnull(Object[] a) {
return a == null ? new Object[0] : a;
}
static BitSet unnull(BitSet b) {
return b == null ? new BitSet() : b;
}
// replacement for class JavaTok
// maybe incomplete, might want to add floating point numbers
// todo also: extended multi-line strings
static int javaTok_n, javaTok_elements;
static boolean javaTok_opt;
static List javaTok(String s) {
return javaTok(s, null);
}
static List javaTok(String s, List existing) {
++javaTok_n;
int nExisting = javaTok_opt && existing != null ? existing.size() : 0;
ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList();
int l = s.length();
int i = 0, n = 0;
while (i < l) {
int j = i;
char c, d;
// scan for whitespace
while (j < l) {
c = s.charAt(j);
d = j+1 >= l ? '\0' : s.charAt(j+1);
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
++j;
else if (c == '/' && d == '*') {
do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/"));
j = Math.min(j+2, l);
} else if (c == '/' && d == '/') {
do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0);
} else
break;
}
if (n < nExisting && javaTok_isCopyable(existing.get(n), s, i, j))
tok.add(existing.get(n));
else
tok.add(quickSubstring(s, i, j));
++n;
i = j;
if (i >= l) break;
c = s.charAt(i);
d = i+1 >= l ? '\0' : s.charAt(i+1);
// scan for non-whitespace
if (c == '\'' || c == '"') {
char opener = c;
++j;
while (j < l) {
if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors
++j;
break;
} else if (s.charAt(j) == '\\' && j+1 < l)
j += 2;
else
++j;
}
} else if (Character.isJavaIdentifierStart(c))
do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't"
else if (Character.isDigit(c)) {
do ++j; while (j < l && Character.isDigit(s.charAt(j)));
if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L
} else if (c == '[' && d == '[') {
do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]"));
j = Math.min(j+2, l);
} else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') {
do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]"));
j = Math.min(j+3, l);
} else
++j;
if (n < nExisting && javaTok_isCopyable(existing.get(n), s, i, j))
tok.add(existing.get(n));
else
tok.add(quickSubstring(s, i, j));
++n;
i = j;
}
if ((tok.size() % 2) == 0) tok.add("");
javaTok_elements += tok.size();
return tok;
}
static List javaTok(List tok) {
return javaTok(join(tok), tok);
}
static boolean javaTok_isCopyable(String t, String s, int i, int j) {
return t.length() == j-i
&& s.regionMatches(i, t, 0, j-i); // << could be left out, but that's brave
}
static Object unstructure(String text) {
return unstructure(text, false);
}
static Object unstructure(String text, final boolean allDynamic) {
return unstructure(text, allDynamic, null);
}
static int structure_internStringsLongerThan = 50;
// classFinder: func(name) -> class (optional)
static Object unstructure(String text, final boolean allDynamic,
final Object classFinder) {
if (text == null) return null;
final List tok = javaTokC(text);
final boolean debug = unstructure_debug;
class X {
int i = 0;
HashMap refs = new HashMap();
HashMap tokrefs = new HashMap();
HashSet concepts = new HashSet();
HashMap classesMap = new HashMap();
Object parse() {
String t = tok.get(i);
int refID = 0;
if (structure_isMarker(t, 0, l(t))) {
refID = parseInt(t.substring(1));
i++;
}
// if (debug) print("parse: " + quote(t));
int tokIndex = i;
Object o = parse_inner(refID, tokIndex);
if (refID != 0)
refs.put(refID, o);
if (o != null)
tokrefs.put(tokIndex, o);
return o;
}
Object parse_inner(int refID, int tokIndex) {
String t = tok.get(i);
// if (debug) print("parse_inner: " + quote(t));
Class c = classesMap.get(t);
if (c == null) {
if (t.startsWith("\"")) {
String s = internIfLongerThan(unquote(tok.get(i)), structure_internStringsLongerThan);
i++;
return s;
}
if (t.startsWith("'"))
return unquoteCharacter(tok.get(i++));
if (t.equals("bigint"))
return parseBigInt();
if (t.equals("d"))
return parseDouble();
if (t.equals("fl"))
return parseFloat();
if (t.equals("false") || t.equals("f")) {
i++; return false;
}
if (t.equals("true") || t.equals("t")) {
i++; return true;
}
if (t.equals("-")) {
t = tok.get(i+1);
i += 2;
return isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t));
}
if (isInteger(t) || isLongConstant(t)) {
i++;
//if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t));
if (isLongConstant(t)) return parseLong(t);
long l = parseLong(t);
boolean isInt = l == (int) l;
if (debug)
print("l=" + l + ", isInt: " + isInt);
return isInt ? (Object) new Integer((int) l) : (Object) new Long(l);
}
if (t.equals("File")) {
File f = new File(unquote(tok.get(i+1)));
i += 2;
return f;
}
if (t.startsWith("r") && isInteger(t.substring(1))) {
i++;
int ref = Integer.parseInt(t.substring(1));
Object o = refs.get(ref);
if (o == null)
print("Warning: unsatisfied back reference " + ref);
return o;
}
if (t.startsWith("t") && isInteger(t.substring(1))) {
i++;
int ref = Integer.parseInt(t.substring(1));
Object o = tokrefs.get(ref);
if (o == null)
print("Warning: unsatisfied token reference " + ref);
return o;
}
if (t.equals("hashset"))
return parseHashSet();
if (t.equals("treeset"))
return parseTreeSet();
if (eqOneOf(t, "hashmap", "hm"))
return parseHashMap();
if (t.equals("{"))
return parseMap();
if (t.equals("["))
return parseList();
if (t.equals("bitset"))
return parseBitSet();
if (t.equals("array") || t.equals("intarray"))
return parseArray();
if (t.equals("ba")) {
String hex = unquote(tok.get(i+1));
i += 2;
return hexToBytes(hex);
}
if (t.equals("boolarray")) {
int n = parseInt(tok.get(i+1));
String hex = unquote(tok.get(i+2));
i += 6;
return boolArrayFromBytes(hexToBytes(hex), n);
}
if (t.equals("class"))
return parseClass();
if (t.equals("l"))
return parseLisp();
if (t.equals("null")) {
i++; return null;
}
/* in dev.
if (!allDynamic && t.equals("run")) {
S snippetID = unquote(t.get(i+1));
i += 2;
run(
}
*/
if (eq(t, "c")) {
consume("c");
t = tok.get(i);
assertTrue(isJavaIdentifier(t));
concepts.add(t);
}
}
if (c == null && !isJavaIdentifier(t))
throw new RuntimeException("Unknown token " + (i+1) + ": " + t);
// any other class name
if (c == null) {
// First, find class
if (allDynamic) c = null;
else if (classFinder != null)
c = (Class) callF(classFinder, t);
else
c = findClass(t);
if (c != null)
classesMap.put(t, c);
}
// Check if it has an outer reference
i++;
boolean hasOuter = eq(get(tok, i), "(") && eq(get(tok, i+1), "this$1");
DynamicObject dO = null;
Object o = null;
if (c != null)
o = hasOuter ? nuStubInnerObject(c) : nuEmptyObject(c);
else {
if (concepts.contains(t) && (c = findClass("Concept")) != null)
o = dO = (DynamicObject) nuEmptyObject(c);
else
dO = new DynamicObject();
dO.className = t;
if (debug) print("Made dynamic object " + t + " " + shortClassName(dO));
}
// Save in references list early because contents of object
// might link back to main object
if (refID != 0)
refs.put(refID, o != null ? o : dO);
tokrefs.put(tokIndex, o != null ? o : dO);
// NOW parse the fields!
Map fields = new TreeMap();
if (i < tok.size() && tok.get(i).equals("(")) {
consume("(");
while (!tok.get(i).equals(")")) {
String key = unquote(tok.get(i));
i++;
consume("=");
Object value = parse();
fields.put(key, value);
if (tok.get(i).equals(",")) i++;
}
consume(")");
}
if (o != null)
if (dO != null) {
if (debug)
printStructure("setOptAllDyn", fields);
setOptAllDyn(dO, fields);
} else
setOptAll(o, fields);
else for (String field : keys(fields))
dO.fieldValues.put(field.intern(), fields.get(field));
if (o != null)
pcallOpt_noArgs(o, "_doneLoading");
return o != null ? o : dO;
}
Object parseSet(Set set) {
set.addAll((List) parseList());
return set;
}
Object parseLisp() {
consume("l");
consume("(");
ArrayList list = new ArrayList();
while (!tok.get(i).equals(")")) {
list.add(parse());
if (tok.get(i).equals(",")) i++;
}
consume(")");
return newObject("main$Lisp", (String) list.get(0), subList(list, 1));
}
Object parseBitSet() {
consume("bitset");
consume("{");
BitSet bs = new BitSet();
while (!tok.get(i).equals("}")) {
bs.set((Integer) parse());
if (tok.get(i).equals(",")) i++;
}
consume("}");
return bs;
}
Object parseList() {
consume("[");
ArrayList list = new ArrayList();
while (!tok.get(i).equals("]")) {
Object o = parse();
//if (debug) print("List element type: " + getClassName(o));
list.add(o);
if (tok.get(i).equals(",")) i++;
}
consume("]");
return list;
}
Object parseArray() {
String type = tok.get(i);
i++;
consume("{");
List list = new ArrayList();
while (!tok.get(i).equals("}")) {
list.add(parse());
if (tok.get(i).equals(",")) i++;
}
consume("}");
if (type.equals("intarray"))
return toIntArray(list);
return list.toArray();
}
Object parseClass() {
consume("class");
consume("(");
String name = tok.get(i);
i++;
consume(")");
Class c = allDynamic ? null : findClass(name);
if (c != null) return c;
DynamicObject dO = new DynamicObject();
dO.className = "java.lang.Class";
dO.fieldValues.put("name", name);
return dO;
}
Object parseBigInt() {
consume("bigint");
consume("(");
String val = tok.get(i);
i++;
if (eq(val, "-")) {
val = "-" + tok.get(i);
i++;
}
consume(")");
return new BigInteger(val);
}
Object parseDouble() {
consume("d");
consume("(");
String val = unquote(tok.get(i));
i++;
consume(")");
return Double.parseDouble(val);
}
Object parseFloat() {
consume("fl");
String val;
if (eq(tok.get(i), "(")) {
consume("(");
val = unquote(tok.get(i));
i++;
consume(")");
} else {
val = unquote(tok.get(i));
i++;
}
return Float.parseFloat(val);
}
Object parseHashMap() {
i++;
return parseMap(new HashMap());
}
Object parseHashSet() {
consume("hashset");
return parseSet(new HashSet());
}
Object parseTreeSet() {
consume("treeset");
return parseSet(new TreeSet());
}
Object parseMap() {
return parseMap(new TreeMap());
}
Object parseMap(Map map) {
consume("{");
while (!tok.get(i).equals("}")) {
Object key = parse();
consume("=");
Object value = parse();
map.put(key, value);
if (tok.get(i).equals(",")) i++;
}
consume("}");
return map;
}
void consume(String s) {
if (!tok.get(i).equals(s)) {
String prevToken = i-1 >= 0 ? tok.get(i-1) : "";
String nextTokens = join(tok.subList(i, Math.min(i+2, tok.size())));
throw fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");
}
i++;
}
}
return new X().parse();
}
static boolean unstructure_debug;
static String _userHome;
static String userHome() {
if (_userHome == null) {
if (isAndroid())
_userHome = "/storage/sdcard0/";
else
_userHome = System.getProperty("user.home");
//System.out.println("userHome: " + _userHome);
}
return _userHome;
}
static File userHome(String path) {
return new File(userDir(), path);
}
static ArrayList litlist(A... a) {
return new ArrayList (Arrays.asList(a));
}
static List toLines(File f) {
return toLines(loadTextFile(f));
}
public 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;
}
private 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 List javaTokC(String s) {
int l = s.length();
ArrayList tok = new ArrayList();
int i = 0;
while (i < l) {
int j = i;
char c, d;
// scan for whitespace
while (j < l) {
c = s.charAt(j);
d = j+1 >= l ? '\0' : s.charAt(j+1);
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
++j;
else if (c == '/' && d == '*') {
do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/"));
j = Math.min(j+2, l);
} else if (c == '/' && d == '/') {
do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0);
} else
break;
}
i = j;
if (i >= l) break;
c = s.charAt(i);
d = i+1 >= l ? '\0' : s.charAt(i+1);
// scan for non-whitespace
if (c == '\'' || c == '"') {
char opener = c;
++j;
while (j < l) {
if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors
++j;
break;
} else if (s.charAt(j) == '\\' && j+1 < l)
j += 2;
else
++j;
}
} else if (Character.isJavaIdentifierStart(c))
do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't"
else if (Character.isDigit(c)) {
do ++j; while (j < l && Character.isDigit(s.charAt(j)));
if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L
} else if (c == '[' && d == '[') {
do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]"));
j = Math.min(j+2, l);
} else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') {
do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]"));
j = Math.min(j+3, l);
} else
++j;
tok.add(quickSubstring(s, i, j));
i = j;
}
return tok;
}
static A assertEquals(Object x, A y) {
return assertEquals(null, x, y);
}
static A assertEquals(String msg, Object x, A y) {
if (!(x == null ? y == null : x.equals(y)))
throw fail((msg != null ? msg + ": " : "") + x + " != " + y);
return y;
}
static File getProgramDir() {
return programDir();
}
static File getProgramDir(String snippetID) {
return programDir(snippetID);
}
static Object call(Object o) {
return callFunction(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) {
try {
if (o instanceof Class) {
Method m = call_findStaticMethod((Class) o, method, args, false);
m.setAccessible(true);
return m.invoke(null, args);
} else {
Method m = call_findMethod(o, method, args, false);
m.setAccessible(true);
return m.invoke(o, args);
}
} catch (Exception e) {
throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e);
}
}
static Method call_findStaticMethod(Class c, String method, Object[] args, boolean debug) {
Class _c = c;
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (!m.getName().equals(method)) {
if (debug) System.out.println("Method name mismatch: " + method);
continue;
}
if ((m.getModifiers() & Modifier.STATIC) == 0 || !call_checkArgs(m, args, debug))
continue;
return m;
}
c = c.getSuperclass();
}
throw new RuntimeException("Method '" + method + "' (static) with " + args.length + " parameter(s) not found in " + _c.getName());
}
static Method call_findMethod(Object o, String method, Object[] args, boolean debug) {
Class c = o.getClass();
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (m.getName().equals(method) && call_checkArgs(m, args, debug))
return m;
}
c = c.getSuperclass();
}
throw new RuntimeException("Method '" + method + "' (non-static) with " + args.length + " parameter(s) not found in " + o.getClass().getName());
}
private static boolean call_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
static HashMap getDeclaredFields_cache = new HashMap();
static Field[] getDeclaredFields_cached(Class c) {
Field[] fields;
synchronized(getDeclaredFields_cache) {
fields = getDeclaredFields_cache.get(c);
if (fields == null) {
getDeclaredFields_cache.put(c, fields = c.getDeclaredFields());
for (Field f : fields)
f.setAccessible(true);
}
}
return fields;
}
static boolean loadBufferedImage_useImageCache = true;
static BufferedImage loadBufferedImage(String snippetIDOrURL) { try {
if (snippetIDOrURL == null) return null;
if (isURL(snippetIDOrURL))
return ImageIO.read(new URL(snippetIDOrURL));
if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL);
String snippetID = "" + parseSnippetID(snippetIDOrURL);
try {
File dir = getCacheProgramDir("Image-Snippets");
if (loadBufferedImage_useImageCache) {
dir.mkdirs();
File file = new File(dir, snippetID + ".png");
if (file.exists() && file.length() != 0)
try {
return ImageIO.read(file);
} catch (Throwable e) {
e.printStackTrace();
// fall back to loading from sourceforge
}
}
String imageURL = snippetImageURL(snippetID);
System.err.println("Loading image: " + imageURL);
BufferedImage image = ImageIO.read(new URL(imageURL));
if (loadBufferedImage_useImageCache) {
File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis());
ImageIO.write(image, "png", tempFile);
tempFile.renameTo(new File(dir, snippetID + ".png"));
//Log.info("Cached image.");
}
//Log.info("Loaded image.");
return image;
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static BufferedImage loadBufferedImage(File file) { try {
return file.isFile() ? ImageIO.read(file) : null;
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String boolArrayToHex(boolean[] a) {
return bytesToHex(boolArrayToBytes(a));
}
static boolean startsWithIgnoreCase(String a, String b) {
return a != null && a.regionMatches(true, 0, b, 0, b.length());
}
static Object first(Object list) {
return ((List) list).isEmpty() ? null : ((List) list).get(0);
}
static A first(List list) {
return list.isEmpty() ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
public static String bytesToHex(byte[] bytes) {
return bytesToHex(bytes, 0, bytes.length);
}
public static String bytesToHex(byte[] bytes, int ofs, int len) {
StringBuilder stringBuilder = new StringBuilder(len*2);
for (int i = 0; i < len; i++) {
String s = "0" + Integer.toHexString(bytes[ofs+i]);
stringBuilder.append(s.substring(s.length()-2, s.length()));
}
return stringBuilder.toString();
}
static RuntimeException asRuntimeException(Throwable t) {
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static Object mc() {
return getMainClass();
}
static String indentx(String s) {
return indentx(indent_default, s);
}
static String indentx(int n, String s) {
return dropSuffix(repeat(' ', n), indent(n, s));
}
static String indentx(String indent, String s) {
return dropSuffix(indent, indent(indent, s));
}
static File programDir_mine; // set this to relocate program's data
static File programDir() {
return programDir(getProgramID());
}
static File programDir(String snippetID) {
if (programDir_mine != null && sameSnippetID(snippetID, programID()))
return programDir_mine;
return new File(javaxDataDir(), formatSnippetID(snippetID));
}
static boolean neq(Object a, Object b) {
return !eq(a, b);
}
// extended over Class.isInstance() to handle primitive types
static boolean isInstanceX(Class type, Object arg) {
if (type == boolean.class) return arg instanceof Boolean;
if (type == int.class) return arg instanceof Integer;
if (type == long.class) return arg instanceof Long;
if (type == float.class) return arg instanceof Float;
if (type == short.class) return arg instanceof Short;
if (type == char.class) return arg instanceof Character;
if (type == byte.class) return arg instanceof Byte;
if (type == double.class) return arg instanceof Double;
return type.isInstance(arg);
}
static String singleFieldName(Class c) {
Set l = listFields(c);
if (l(l) != 1)
throw fail("No single field found in " + c + " (have " + n(l(l), "fields") + ")");
return first(l);
}
static int month() {
return Calendar.getInstance().get(Calendar.MONTH)+1;
}
static Rectangle screenRectangle() {
return new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
}
static String loadGZTextFile(File file) { try {
if (!file.isFile()) return null;
ByteArrayOutputStream fos = new ByteArrayOutputStream();
InputStream fis = new FileInputStream(file);
GZIPInputStream gis = new GZIPInputStream(fis);
try {
byte[] buffer = new byte[1024];
int len;
while((len = gis.read(buffer)) != -1){
fos.write(buffer, 0, len);
}
} finally {
fis.close();
}
fos.close();
return fromUtf8(fos.toByteArray()); // TODO: use a Reader
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static boolean containsNewLine(String s) {
return contains(s, '\n'); // screw \r, nobody needs it
}
public static File mkdirsForFile(File file) {
File dir = file.getParentFile();
if (dir != null) // is null if file is in current dir
dir.mkdirs();
return file;
}
static Object callOpt(Object o) {
if (o == null) return null;
return callF(o);
}
static Object callOpt(Object o, String method, Object... args) {
try {
if (o == null) return null;
if (o instanceof Class) {
Method m = callOpt_findStaticMethod((Class) o, method, args, false);
if (m == null) return null;
m.setAccessible(true);
return m.invoke(null, args);
} else {
Method m = callOpt_findMethod(o, method, args, false);
if (m == null) return null;
m.setAccessible(true);
return m.invoke(o, args);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Method callOpt_findStaticMethod(Class c, String method, Object[] args, boolean debug) {
Class _c = c;
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (!m.getName().equals(method)) {
if (debug) System.out.println("Method name mismatch: " + method);
continue;
}
if ((m.getModifiers() & Modifier.STATIC) == 0 || !callOpt_checkArgs(m, args, debug))
continue;
return m;
}
c = c.getSuperclass();
}
return null;
}
static Method callOpt_findMethod(Object o, String method, Object[] args, boolean debug) {
Class c = o.getClass();
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (m.getName().equals(method) && callOpt_checkArgs(m, args, debug))
return m;
}
c = c.getSuperclass();
}
return null;
}
private static boolean callOpt_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
static String fromLines(List lines) {
StringBuilder buf = new StringBuilder();
if (lines != null)
for (String line : lines)
buf.append(line).append('\n');
return buf.toString();
}
static String fromLines(String... lines) {
return fromLines(asList(lines));
}
static String substring(String s, int x) {
return safeSubstring(s, x);
}
static String substring(String s, int x, int y) {
return safeSubstring(s, x, y);
}
static final WeakHashMap> getOpt_cache = new WeakHashMap();
static final HashMap getOpt_special = new HashMap(); // just a marker
static {
getOpt_cache.put(Class.class, getOpt_special);
getOpt_cache.put(String.class, getOpt_special);
}
static Object getOpt_cached(Object o, String field) { try {
if (o == null) return null;
Class c = o.getClass();
HashMap map;
synchronized(getOpt_cache) {
map = getOpt_cache.get(c);
if (map == null)
map = getOpt_makeCache(c);
}
if (map == getOpt_special) {
if (o instanceof Class)
return getOpt((Class) o, field);
if (o instanceof String)
return getOpt(getBot((String) o), field);
if (o instanceof Map)
return ((Map) o).get(field);
}
Field f = map.get(field);
if (f != null) return f.get(o);
if (o instanceof DynamicObject)
return ((DynamicObject) o).fieldValues.get(field);
return null;
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
// used internally - we are in synchronized block
static HashMap getOpt_makeCache(Class c) {
HashMap map;
if (isSubtypeOf(c, Map.class))
map = getOpt_special;
else {
map = new HashMap();
Class _c = c;
do {
for (Field f : _c.getDeclaredFields()) {
f.setAccessible(true);
String name = f.getName();
if (!map.containsKey(name))
map.put(name, f);
}
_c = _c.getSuperclass();
} while (_c != null);
}
getOpt_cache.put(c, map);
return map;
}
static List emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static List synchroList() {
return Collections.synchronizedList(new ArrayList ());
}
static List synchroList(List l) {
return Collections.synchronizedList(l);
}
static FileOutputStream newFileOutputStream(File path) throws IOException {
return newFileOutputStream(path.getPath());
}
static FileOutputStream newFileOutputStream(String path) throws IOException {
return newFileOutputStream(path, false);
}
static FileOutputStream newFileOutputStream(String path, boolean append) throws IOException {
FileOutputStream f = new // Line break for ancient translator
FileOutputStream(path, append);
callJavaX("registerIO", f, path, true);
return f;
}
public static File mkdirsFor(File file) {
return mkdirsForFile(file);
}
static String padLeft(String s, char c, int n) {
return rep(c, n-l(s)) + s;
}
public static String loadTextFile(String fileName) {
try {
return loadTextFile(fileName, null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String loadTextFile(String fileName, String defaultContents) throws IOException {
if (!new File(fileName).exists())
return defaultContents;
FileInputStream fileInputStream = new FileInputStream(fileName);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
return loadTextFile(inputStreamReader);
}
public static String loadTextFile(File fileName) {
try {
return loadTextFile(fileName, null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String loadTextFile(File fileName, String defaultContents) throws IOException {
try {
return loadTextFile(fileName.getPath(), defaultContents);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public 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 builder.toString();
}
static boolean isEmpty(Collection c) {
return c == null || c.isEmpty();
}
static boolean isEmpty(CharSequence s) {
return s == null || s.length() == 0;
}
static boolean isEmpty(Object[] a) {
return a == null || a.length == 0;
}
static boolean isEmpty(Map map) {
return map == null || map.isEmpty();
}
static boolean nempty(Collection c) {
return !isEmpty(c);
}
static boolean nempty(CharSequence s) {
return !isEmpty(s);
}
static boolean nempty(Object[] o) {
return !isEmpty(o);
}
static boolean nempty(Map m) {
return !isEmpty(m);
}
static boolean nempty(Iterator i) {
return i != null && i.hasNext();
}
static String dropSuffix(String suffix, String s) {
return s.endsWith(suffix) ? s.substring(0, l(s)-l(suffix)) : s;
}
static void smartSet(Field f, Object o, Object value) throws Exception {
f.setAccessible(true);
// take care of common case (long to int)
if (f.getType() == int.class && value instanceof Long)
value = ((Long) value).intValue();
f.set(o, value);
}
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 containsIgnoreCase(List l, String s) {
for (String x : l)
if (eqic(x, s))
return true;
return false;
}
static boolean containsIgnoreCase(String[] l, String s) {
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 String dynamicClassName(Object o) {
if (o instanceof DynamicObject && ((DynamicObject) o).className != null)
return "main$" + ((DynamicObject) o).className;
return className(o);
}
static long round(double d) {
return Math.round(d);
}
static A popLast(List l) {
return liftLast(l);
}
static void copyStream(InputStream in, OutputStream out) { try {
byte[] buf = new byte[65536];
while (true) {
int n = in.read(buf);
if (n <= 0) return;
out.write(buf, 0, n);
}
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static int stdcompare(String a, String b) {
return a == null ? b == null ? 0 : -1 : a.compareTo(b);
}
static int stdcompare(long a, long b) {
return a < b ? -1 : a > b ? 1 : 0;
}
// This is for main classes that are all static.
// (We don't go to base classes.)
static Set listFields(Object c) {
TreeSet fields = new TreeSet();
for (Field f : _getClass(c).getDeclaredFields())
fields.add(f.getName());
return fields;
}
static boolean isURL(String s) {
return s.startsWith("http://") || s.startsWith("https://");
}
static boolean isAWTThread() {
return isTrue(callOpt(getClass("javax.swing.SwingUtilities"), "isEventDispatchThread"));
}
static Thread currentThread() {
return Thread.currentThread();
}
static Map transformKeys(Map map, Object f) {
HashMap m = new HashMap();
for (Object key : keys(map))
m.put(callF(f, key), map.get(key));
return m;
}
static byte[] hexToBytes(String s) {
int n = l(s) / 2;
byte[] bytes = new byte[n];
for (int i = 0; i < n; i++) {
String hex = substring(s, i*2, i*2+2);
try {
bytes[i] = (byte) parseHexByte(hex);
} catch (Throwable _e) {
throw fail("Bad hex byte: " + quote(hex) + " at " + i*2 + "/" + l(s));
}
}
return bytes;
}
// returns l(s) if not found
static int xIndexOf(String s, String sub, int i) {
if (s == null) return 0;
i = s.indexOf(sub, min(i, l(s)));
return i >= 0 ? i : l(s);
}
static int xIndexOf(String s, String sub) {
return xIndexOf(s, sub, 0);
}
static int xIndexOf(String s, char c) {
if (s == null) return 0;
int i = s.indexOf(c);
return i >= 0 ? i : l(s);
}
static String standardCredentials() {
String user = standardCredentialsUser();
String pass = trim(loadTextFile(new File(userHome(), ".tinybrain/userpass")));
if (nempty(user) && nempty(pass))
return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass);
return "";
}
static HashMap nuEmptyObject_cache = new HashMap();
static A nuEmptyObject(Class c) { try {
Constructor ctr;
synchronized(nuEmptyObject_cache) {
ctr = nuEmptyObject_cache.get(c);
if (ctr == null) {
nuEmptyObject_cache.put(c, ctr = nuEmptyObject_findConstructor(c));
ctr.setAccessible(true);
}
}
return (A) ctr.newInstance();
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static Constructor nuEmptyObject_findConstructor(Class c) {
for (Constructor m : c.getDeclaredConstructors())
if (m.getParameterTypes().length == 0)
return m;
throw fail("No default constructor declared in " + c.getName());
}
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 setOptAllDyn_debug;
static void setOptAllDyn(DynamicObject o, Map fields) {
if (fields == null) return;
for (String field : keys(fields)) {
Object val = fields.get(field);
boolean has = hasField(o, field);
if (has)
setOpt(o, field, val);
else {
o.fieldValues.put(field.intern(), val);
if (setOptAllDyn_debug) print("setOptAllDyn added dyn " + field + " to " + o + " [value: " + val + ", fieldValues = " + systemHashCode(o.fieldValues) + ", " + struct(keys(o.fieldValues)) + "]");
}
}
}
static String quickSubstring(String s, int i, int j) {
if (i == j) return "";
return s.substring(i, j);
}
static A liftLast(List l) {
if (l.isEmpty()) return null;
int i = l(l)-1;
A a = l.get(i);
l.remove(i);
return a;
}
static boolean structure_isMarker(String s, int i, int j) {
if (i >= j) return false;
if (s.charAt(i) != 'm') return false;
++i;
while (i < j) {
char c = s.charAt(i);
if (c < '0' || c > '9') return false;
++i;
}
return true;
}
static Object newObject(Class c, Object... args) {
return nuObject(c, args);
}
static Object newObject(String className, Object... args) {
return nuObject(className, args);
}
static Class getMainClass() {
return main.class;
}
static Class getMainClass(Object o) { try {
return (o instanceof Class ? (Class) o : o.getClass()).getClassLoader().loadClass("main");
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static List subList(List l, int startIndex) {
return subList(l, startIndex, l(l));
}
static List subList(List l, int startIndex, int endIndex) {
startIndex = max(0, min(l(l), startIndex));
endIndex = max(0, min(l(l), endIndex));
if (startIndex > endIndex) return litlist();
return l.subList(startIndex, endIndex);
}
static String n(long l, String name) {
return l + " " + (l == 1 ? singular(name) : getPlural(name));
}
static int days() {
return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
}
static Map trimValues(Map map) {
Map map2 = similarEmptyMap(map);
for (A key : keys(map))
map2.put(key, trim(map.get(key)));
return map2;
}
static boolean isInteger(String s) {
if (s == null) return false;
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 getStackTrace(Throwable throwable) {
StringWriter writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
static String formatSnippetID(String id) {
return "#" + parseSnippetID(id);
}
static String formatSnippetID(long id) {
return "#" + id;
}
static String rep(int n, char c) {
return repeat(c, n);
}
static String rep(char c, int n) {
return repeat(c, n);
}
static List rep(A a, int n) {
return repeat(a, n);
}
static String snippetImageURL(String snippetID) {
long id = parseSnippetID(snippetID);
String url;
if (id == 1000010 || id == 1000012)
url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + id;
else
url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id
+ "&contentType=image/png";
return url;
}
static Object callJavaX(String method, Object... args) {
return callOpt(getJavaX(), method, args);
}
public static String unquote(String s) {
if (s == null) return null;
if (s.startsWith("[")) {
int i = 1;
while (i < s.length() && s.charAt(i) == '=') ++i;
if (i < s.length() && s.charAt(i) == '[') {
String m = s.substring(1, i);
if (s.endsWith("]" + m + "]"))
return s.substring(i+1, s.length()-i-1);
}
}
if (s.startsWith("\"") /*&& s.endsWith("\"")*/ && s.length() > 1) {
int l = s.endsWith("\"") ? s.length()-1 : s.length();
StringBuilder sb = new StringBuilder(l-1);
for (int i = 1; i < l; i++) {
char ch = s.charAt(i);
if (ch == '\\') {
char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1);
// Octal escape?
if (nextChar >= '0' && nextChar <= '7') {
String code = "" + nextChar;
i++;
if ((i < l - 1) && s.charAt(i + 1) >= '0'
&& s.charAt(i + 1) <= '7') {
code += s.charAt(i + 1);
i++;
if ((i < l - 1) && s.charAt(i + 1) >= '0'
&& s.charAt(i + 1) <= '7') {
code += s.charAt(i + 1);
i++;
}
}
sb.append((char) Integer.parseInt(code, 8));
continue;
}
switch (nextChar) {
case '\\':
ch = '\\';
break;
case 'b':
ch = '\b';
break;
case 'f':
ch = '\f';
break;
case 'n':
ch = '\n';
break;
case 'r':
ch = '\r';
break;
case 't':
ch = '\t';
break;
case '\"':
ch = '\"';
break;
case '\'':
ch = '\'';
break;
// Hex Unicode: u????
case 'u':
if (i >= l - 5) {
ch = 'u';
break;
}
int code = Integer.parseInt(
"" + s.charAt(i + 2) + s.charAt(i + 3)
+ s.charAt(i + 4) + s.charAt(i + 5), 16);
sb.append(Character.toChars(code));
i += 5;
continue;
default:
ch = nextChar; // added by Stefan
}
i++;
}
sb.append(ch);
}
return sb.toString();
}
return s; // not quoted - return original
}
static void setOptAll(Object o, Map fields) {
if (fields == null) return;
for (String field : keys(fields))
setOpt(o, field, fields.get(field));
}
static void setOptAll(Object o, Object... values) {
//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];
setOpt(o, field, value);
}
}
static char unquoteCharacter(String s) {
assertTrue(s.startsWith("'") && s.length() > 1);
return unquote("\"" + s.substring(1, s.endsWith("'") ? s.length()-1 : s.length()) + "\"").charAt(0);
}
static int parseInt(String s) {
return empty(s) ? 0 : Integer.parseInt(s);
}
static A nuStubInnerObject(Class c) { try {
Class outerType = getOuterClass(c);
Constructor m = c.getDeclaredConstructor(outerType);
m.setAccessible(true);
return (A) m.newInstance(new Object[] {null});
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String urlencode(String x) {
try {
return URLEncoder.encode(unnull(x), "UTF-8");
} catch (UnsupportedEncodingException e) { throw new RuntimeException(e); }
}
static boolean[] boolArrayFromBytes(byte[] a, int n) {
boolean[] b = new boolean[n];
int m = min(n, l(a)*8);
for (int i = 0; i < m; i++)
b[i] = (a[i/8] & 1 << (i & 7)) != 0;
return b;
}
// hopefully covers all cases :)
static String safeSubstring(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 safeSubstring(String s, int x) {
return safeSubstring(s, x, l(s));
}
public static List parseSnippetIDs(List snippetIDs) {
List l = new ArrayList();
for (String id : snippetIDs)
l.add(str(parseSnippetID(id)));
return l;
}
static Object getBot(String botID) {
return callOpt(getMainBot(), "getBot", botID);
}
static byte[] boolArrayToBytes(boolean[] a) {
byte[] b = new byte[(l(a)+7)/8];
for (int i = 0; i < l(a); i++)
if (a[i])
b[i/8] |= 1 << (i & 7);
return b;
}
static String className(Object o) {
return getClassName(o);
}
static File getCacheProgramDir() {
return getCacheProgramDir(getProgramID());
}
static File getCacheProgramDir(String snippetID) {
return new File(userHome(), "JavaX-Caches/" + formatSnippetIDOpt(snippetID));
}
static ThreadLocal loadPage_charset = new ThreadLocal();
static boolean loadPage_allowGzip = true, loadPage_debug;
static boolean loadPage_anonymous; // don't send computer ID
static int loadPage_verboseness = 100000;
static int loadPage_retries = 60; // seconds
public static String loadPageSilently(String url) {
try {
return loadPageSilently(new URL(loadPage_preprocess(url)));
} catch (IOException e) { throw new RuntimeException(e); }
}
public static String loadPageSilently(URL url) {
try {
IOException e = null;
for (int tries = 0; tries < loadPage_retries; tries++)
try {
URLConnection con = openConnection(url);
return loadPage(con, url);
} catch (IOException _e) {
e = _e;
if (loadPageThroughProxy_enabled) {
print("Trying proxy because of: " + e);
try {
return loadPageThroughProxy(str(url));
} catch (Throwable e2) {
print(" " + exceptionToStringShort(e2));
}
}
sleepSeconds(1);
}
throw e;
} catch (IOException e) { throw new RuntimeException(e); }
}
static String loadPage_preprocess(String url) {
if (url.startsWith("tb/"))
url = "tinybrain.de:8080/" + url;
if (url.indexOf("://") < 0)
url = "http://" + url;
return url;
}
public static String loadPage(String url) {
try {
url = loadPage_preprocess(url);
print("Loading: " + hideCredentials(url));
return loadPageSilently(new URL(url));
} catch (IOException e) { throw new RuntimeException(e); }
}
public static String loadPage(URL url) {
print("Loading: " + hideCredentials(url.toExternalForm()));
return loadPageSilently(url);
}
public static String loadPage(URLConnection con, URL url) throws IOException {
try {
if (!loadPage_anonymous) {
String computerID = getComputerID();
if (computerID != null)
con.setRequestProperty("X-ComputerID", computerID);
}
if (loadPage_allowGzip)
con.setRequestProperty("Accept-Encoding", "gzip");
} catch (Throwable e) {} // fails if within doPost
String contentType = con.getContentType();
if (contentType == null)
throw new IOException("Page could not be read: " + url);
//print("Content-Type: " + contentType);
String charset = loadPage_charset == null ? null : loadPage_charset.get();
if (charset == null) charset = loadPage_guessCharset(contentType);
InputStream in = con.getInputStream();
if ("gzip".equals(con.getContentEncoding())) {
if (loadPage_debug)
print("loadPage: Using gzip.");
in = new GZIPInputStream(in);
}
Reader r = new InputStreamReader(in, charset);
StringBuilder buf = new StringBuilder();
int n = 0;
while (true) {
int ch = r.read();
if (ch < 0)
break;
buf.append((char) ch);
++n;
if ((n % loadPage_verboseness) == 0) print(" " + n + " chars read");
}
return buf.toString();
}
static String loadPage_guessCharset(String contentType) {
Pattern p = Pattern.compile("text/[a-z]+;\\s+charset=([^\\s]+)\\s*");
Matcher m = p.matcher(contentType);
String match = m.matches() ? m.group(1) : null;
if (loadPage_debug)
print("loadPage: contentType=" + contentType + ", match: " + match);
/* If Content-Type doesn't match this pre-conception, choose default and hope for the best. */
return or(match, "ISO-8859-1");
}
public static boolean isSnippetID(String s) {
try {
parseSnippetID(s);
return true;
} catch (RuntimeException e) {
return false;
}
}
static void assertTrue(Object o) {
assertEquals(true, o);
}
static boolean assertTrue(String msg, boolean b) {
if (!b)
throw fail(msg);
return b;
}
static boolean assertTrue(boolean b) {
if (!b)
throw fail("oops");
return b;
}
static boolean isLongConstant(String s) {
if (!s.endsWith("L")) return false;
s = s.substring(0, l(s)-1);
return isInteger(s);
}
static boolean endsWithLetter(String s) {
return nempty(s) && isLetter(last(s));
}
static String internIfLongerThan(String s, int l) {
return s == null ? null : l(s) >= l ? s.intern() : s;
}
static void pcallOpt_noArgs(Object o, String method) {
try { /* pcall 1*/ callOpt_noArgs(o, method); /* pcall 2 */ } catch (Throwable __e) { printStackTrace(__e); }
}
static Map jsonDecodeMap(String s) {
Object o = jsonDecode(s);
if (o instanceof Map)
return (Map) o;
else
throw fail("Not a JSON map: " + s);
}
static boolean sameSnippetID(String a, String b) {
return a != null && b != null && parseSnippetID(a) == parseSnippetID(b);
}
// works on lists and strings and null
static int indexOfIgnoreCase(Object a, Object b) {
if (a == null) return -1;
if (a instanceof String) {
Matcher m = Pattern.compile((String) b, Pattern.CASE_INSENSITIVE + Pattern.LITERAL).matcher((String) a);
if (m.find()) return m.start(); else return -1;
}
if (a instanceof List) {
for (int i = 0; i < ((List) a).size(); i++) {
Object o = ((List) a).get(i);
if (o != null && ((String) o).equalsIgnoreCase((String) b))
return i;
}
return -1;
}
throw fail("Unknown type: " + a);
}
static int[] toIntArray(List l) {
int[] a = new int[l(l)];
for (int i = 0; i < a.length; i++)
a[i] = l.get(i);
return a;
}
static void printStructure(String prefix, Object o) {
if (endsWithLetter(prefix)) prefix += ": ";
print(prefix + structure(o));
}
static void printStructure(Object o) {
print(structure(o));
}
static boolean eqOneOf(Object o, Object... l) {
for (Object x : l) if (eq(o, x)) return true; return false;
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return Collections.synchronizedMap(map);
}
static int indent_default = 2;
static String indent(int indent) {
return repeat(' ', indent);
}
static String indent(int indent, String s) {
return indent(repeat(' ', indent), s);
}
static String indent(String indent, String s) {
return indent + s.replace("\n", "\n" + indent);
}
static String indent(String s) {
return indent(indent_default, s);
}
static List indent(String indent, List lines) {
List l = new ArrayList();
for (String s : lines)
l.add(indent + s);
return l;
}
static double parseDouble(String s) {
return Double.parseDouble(s);
}
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 repeat(char c, int n) {
n = max(n, 0);
char[] chars = new char[n];
for (int i = 0; i < n; i++)
chars[i] = c;
return new String(chars);
}
static List repeat(A a, int n) {
List l = new ArrayList ();
for (int i = 0; i < n; i++)
l.add(a);
return l;
}
static String fromUtf8(byte[] bytes) { try {
return new String(bytes, "UTF-8");
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static File userDir() {
return new File(userHome());
}
static File userDir(String path) {
return new File(userHome(), path);
}
static boolean isAndroid() { return System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0; }
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 String shortenSnippetID(String snippetID) {
if (snippetID.startsWith("#"))
snippetID = snippetID.substring(1);
String httpBlaBla = "http://tinybrain.de/";
if (snippetID.startsWith(httpBlaBla))
snippetID = snippetID.substring(httpBlaBla.length());
return "" + parseLong(snippetID);
}
static List getPlural_specials = ll("sheep", "fish");
static String getPlural(String s) {
if (containsIgnoreCase(getPlural_specials, s)) return s;
if (ewic(s, "y")) return dropSuffixIgnoreCase("y", s) + "ies";
if (ewic(s, "ss")) return s + "es";
if (ewic(s, "s")) return s;
return s + "s";
}
static Map singular_specials = litmap(
"children", "child", "images", "image", "chess", "chess");
static Set singular_specials2 = litset("time");
static String singular(String s) {
if (s == null) return null;
s = toLower(s);
{ String _a_1 = singular_specials.get(s); if (!empty(_a_1)) return _a_1; }
if (singular_specials2.contains(dropSuffix("s", s)))
return dropSuffix("s", s);
if (s.endsWith("ness")) return s;
if (s.endsWith("ges")) return dropSuffix("s", s);
s = dropSuffix("es", s);
s = dropSuffix("s", s);
return s;
}
static Object mainBot;
static Object getMainBot() {
return mainBot;
}
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 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 byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x) x = d;
return x;
}
static String hideCredentials(String url) {
return url.replaceAll("&_pass=[^&]*", "&_pass=");
}
static Class __javax;
static Class getJavaX() {
return __javax;
}
static String exceptionToStringShort(Throwable e) {
e = getInnerException(e);
String msg = unnull(e.getMessage());
if (msg.indexOf("Error") < 0 && msg.indexOf("Exception") < 0)
return baseClassName(e) + ": " + msg;
else
return msg;
}
// hmm, this shouldn't call functions really. That was just
// for coroutines.
static boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
return ((Boolean) callF(o)).booleanValue();
}
static boolean isTrue(Object pred, Object arg) {
return booleanValue(callF(pred, arg));
}
static boolean hasField(Object o, String field) {
return findField2(o, field) != null;
}
static Object jsonDecode(final String text) {
final List tok = jsonTok(text);
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 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 = 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 Class> _getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null;
}
}
static Class _getClass(Object o) {
return o instanceof Class ? (Class) o : o.getClass();
}
static Class _getClass(Object realm, String name) { try {
return getClass(realm).getClassLoader().loadClass(classNameToVM(name));
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static A last(List l) {
return l.isEmpty() ? null : l.get(l.size()-1);
}
static char last(String s) {
return empty(s) ? '#' : s.charAt(l(s)-1);
}
static URLConnection openConnection(URL url) { try {
ping();
return url.openConnection();
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static int systemHashCode(Object o) {
return identityHashCode(o);
}
static Map similarEmptyMap(Map m) {
if (m instanceof TreeMap) return new TreeMap();
if (m instanceof LinkedHashMap) return new LinkedHashMap();
// default to a hash map
return new HashMap();
}
static Map synchroHashMap() {
return Collections.synchronizedMap(new HashMap());
}
static Class getOuterClass(Class c) { try {
String s = c.getName();
int i = s.lastIndexOf('$');
return Class.forName(substring(s, 0, i));
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String standardCredentialsUser() {
return trim(loadTextFile(new File(userHome(), ".tinybrain/username")));
}
static String getComputerID() { try {
return computerID();
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
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 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 byte max(byte[] c) {
byte x = -128;
for (byte d : c) if (d > x) x = d;
return x;
}
static final boolean loadPageThroughProxy_enabled = false;
static String loadPageThroughProxy(String url) {
return null;
}
static Class> getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null;
}
}
static Class getClass(Object o) {
return o instanceof Class ? (Class) o : o.getClass();
}
static Class getClass(Object realm, String name) { try {
try {
return getClass(realm).getClassLoader().loadClass(classNameToVM(name));
} catch (ClassNotFoundException e) {
return null;
}
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static boolean isLetter(char c) {
return Character.isLetter(c);
}
static String formatSnippetIDOpt(String s) {
return isSnippetID(s) ? formatSnippetID(s) : s;
}
static A or(A a, A b) {
return a != null ? a : b;
}
static int parseHexByte(String s) {
return Integer.parseInt(s, 16);
}
static HashSet litset(A... items) {
return lithashset(items);
}
static String dropSuffixIgnoreCase(String suffix, String s) {
return ewic(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s;
}
static Throwable getInnerException(Throwable e) {
while (e.getCause() != null)
e = e.getCause();
return e;
}
static String _computerID;
public static String computerID() { try {
if (_computerID == null) {
File file = new File(userHome(), ".tinybrain/computer-id");
_computerID = loadTextFile(file.getPath(), null);
if (_computerID == null) {
_computerID = makeRandomID(12);
saveTextFile(file.getPath(), _computerID);
}
}
return _computerID;
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String classNameToVM(String name) {
return name.replace(".", "$");
}
static List jsonTok(String s) {
List tok = new ArrayList();
int l = s.length();
int i = 0;
while (i < l) {
int j = i;
char c; String cc;
// scan for whitespace
while (j < l) {
c = s.charAt(j);
cc = s.substring(j, Math.min(j+2, l));
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
++j;
else if (cc.equals("/*")) {
do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/"));
j = Math.min(j+2, l);
} else if (cc.equals("//")) {
do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0);
} else
break;
}
tok.add(s.substring(i, j));
i = j;
if (i >= l) break;
c = s.charAt(i); // cc is not needed in rest of loop body
// scan for non-whitespace (json strings, "null" identifier, numbers. everything else automatically becomes a one character token.)
if (c == '\'' || c == '"') {
char opener = c;
++j;
while (j < l) {
if (s.charAt(j) == opener) {
++j;
break;
} else if (s.charAt(j) == '\\' && j+1 < l)
j += 2;
else
++j;
}
} else if (Character.isLetter(c))
do ++j; while (j < l && Character.isLetter(s.charAt(j)));
else if (Character.isDigit(c))
do ++j; while (j < l && Character.isDigit(s.charAt(j)));
else
++j;
tok.add(s.substring(i, j));
i = j;
}
if ((tok.size() % 2) == 0) tok.add("");
return tok;
}
static Field findField2(Object o, String field) {
if (o instanceof Class) return findField2_findStaticField((Class) o, field);
return findField2_findField(o.getClass(), field);
}
static Field findField2_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static Field findField2_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);
return null;
}
static int identityHashCode(Object o) {
return System.identityHashCode(o);
}
static String baseClassName(String className) {
return substring(className, className.lastIndexOf('.'));
}
static String baseClassName(Object o) {
return baseClassName(getClassName(o));
}
static boolean ewic(String a, String b) {
return endsWithIgnoreCase(a, b);
}
static String toLower(String s) {
return s == null ? null : s.toLowerCase();
}
static char toLower(char c) {
return Character.toLowerCase(c);
}
static boolean booleanValue(Object o) {
return eq(true, o);
}
static HashSet lithashset(A... items) {
HashSet set = new HashSet ();
for (A a : items) set.add(a);
return set;
}
static String makeRandomID(int length) {
Random random = new Random();
char[] id = new char[length];
for (int i = 0; i < id.length; i++)
id[i] = (char) ((int) 'a' + random.nextInt(26));
return new String(id);
}
static boolean endsWithIgnoreCase(String a, String b) {
return a != null && l(a) >= l(b) && a.regionMatches(true, l(a)-l(b), b, 0, l(b));
}
static class Pt {
int x, y;
Pt() {}
Pt(Point p) {
x = p.x;
y = p.y;
}
Pt(int x, int y) {
this.y = y;
this.x = x;}
Point getPoint() {
return new Point(x, y);
}
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
public String toString() {
return x + ", " + y;
}
}
// Note: requires e.g. #1005530 - PIF Classes (Clip, Found, FullySearched, Screenshot)
static class ImageFinder {
List screenshots = synchroList();
List clips = synchroList();
float similarity = 0.999f;
int maxCopiesPerClip = 100;
Integer maxTotal; // max total clips found per screenshot
//LinkedBlockingDeque queue = new LinkedBlockingDeque();
boolean quickSearch_clipBufferedImage = true;
ImageFinder() {}
ImageFinder(List screenshots, List clips) {
this.clips = clips;
this.screenshots = screenshots;}
ImageFinder(Screenshot screenshot, List clips) { this(ll(screenshot), clips); }
void run() {
for (Screenshot s : cloneList(screenshots))
searchScreenshot(s);
}
void searchScreenshot(Screenshot screenshot) {
print("Searching screenshot " + screenshot.id);
Var screen = new Var();
// Order clips by last found
/*LinkedHashSet clips = new LinkedHashSet();
for (Found found : reversed(list(Found)))
addIfNotNull(clips, found.clip!);
addAll(clips, reversed(list(Clip)));*/
quickSearch(screenshot, screen);
if (!foundEnough(screenshot))
it: for (Clip clip : clips) {
if (findConcept(FullySearched.class, "screenshot", screenshot, "clip", clip) != null) continue;
print(" Searching " + clip.description);
if (!screenshot.hasImage()) continue;
if (!screen.has())
screen.set(new BWImage(screenshot.loadImage()));
bwRawImageSearch_verbose = true;
bwRawImageSearch_maxEntries = maxCopiesPerClip;
for (FoundImg fi : bwRawImageSearch(screen.v, clip.img, similarity)) {
uniq(Found.class, "screenshot", screenshot, "clip", clip, "fi", fi);
if (foundEnough(screenshot)) break it;
}
uniq(FullySearched.class, "screenshot", screenshot, "clip", clip);
}
print("Done searching screenshot");
}
void quickSearch(Screenshot screenshot, Var screen) {
HashMap lastPosition = new HashMap();
for (Found found : reversed(list(Found.class)))
if (!lastPosition.containsKey(found.clip.get()))
lastPosition.put(found.clip.get(), found.fi.r);
for (Clip clip : keys(lastPosition)) try { /* pcall 1*/
if (!clips.contains(clip)) continue;
if (findConcept(FullySearched.class, "screenshot", screenshot, "clip", clip) != null) continue;
Rect pos = lastPosition.get(clip);
print(" Quick-Searching " + clip.description + " at " + struct(pos));
BWImage pat = clip.img;
int wp = pat.getWidth(), hp = pat.getHeight();
float maxError = (1f-similarity)*wp*hp;
float diff;
if (quickSearch_clipBufferedImage) {
// TODO: cache image
BWImage big = new BWImage(clipBufferedImage(screenshot.loadImage(), new Rectangle(pos.x, pos.y, wp, hp)));
diff = bwImageSectionsSimilarity(big, pat, 0, 0, maxError);
} else {
if (!screen.has())
screen.set(new BWImage(screenshot.loadImage()));
diff = bwImageSectionsSimilarity(screen.v, pat, pos.x, pos.y, maxError);
}
if (diff <= maxError) {
float sim = 1-diff/(wp*hp);
FoundImg fi = new FoundImg(pos, sim);
print(" Found!");
uniq(Found.class, "screenshot", screenshot, "clip", clip, "fi", fi);
if (foundEnough(screenshot)) break;
}
/* pcall 2 */ } catch (Throwable __e) { printStackTrace(__e); }
}
boolean foundEnough(Screenshot screenshot) {
return maxTotal != null && l(findBackRefs(screenshot, Found.class)) >= maxTotal;
}
}
static class Str extends Concept {
String name;
List otherNames = new ArrayList();
Str() {}
Str(String name) {
this.name = name;}
public String toString() { return name; }
}
static class FoundImg {
Rect r;
float sim; // similarity in 0 to 1
FoundImg() {}
FoundImg(Rect r, float sim) {
this.sim = sim;
this.r = r;}
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
}
static class Rect {
int x, y, w, h;
Rect() {}
Rect(Rectangle r) {
x = r.x;
y = r.y;
w = r.width;
h = r.height;
}
Rect(int x, int y, int w, int h) {
this.h = h;
this.w = w;
this.y = y;
this.x = x;}
Rectangle getRectangle() {
return new Rectangle(x, y, w, h);
}
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
public String toString() {
return x + "," + y + " / " + w + "," + h;
}
int x2() { return x + w; }
int y2() { return y + h; }
}
static boolean DynamicObject_loading;
static class DynamicObject {
String className; // just the name, without the "main$"
Map fieldValues = new TreeMap();
DynamicObject() {}
// className = just the name, without the "main$"
DynamicObject(String className) {
this.className = className;}
}
static class Pair {
A a;
B b;
Pair() {}
Pair(A a, B b) {
this.b = b;
this.a = a;}
public int hashCode() {
return main.hashCode(a) + 2*main.hashCode(b);
}
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Pair)) return false;
Pair t = (Pair) o;
return eq(a, t.a) && eq(b, t.b);
}
}
static class BWImage {
private int width, height;
private BWImageSimpleStorage storage;
// color returned when getPixel is called with a position outside the actual image
private float borderColor = 0.0f;
// for unstructure()
BWImage() {}
// BLACK! [Inefficient...]
public BWImage(int width, int height) {
this.width = width;
this.height = height;
byte[] bytePixels = new byte[width*height];
storage = makeStorage(width, height, bytePixels);
}
public BWImage(int width, int height, float[] pixels) {
this.width = width;
this.height = height;
byte[] bytePixels = new byte[pixels.length];
for (int i = 0; i < pixels.length; i++)
bytePixels[i] = toByte(pixels[i]);
storage = makeStorage(width, height, bytePixels);
}
private BWImageSimpleStorage makeStorage(int width, int height, byte[] bytePixels) {
return new BWImageSimpleStorage(width, height, bytePixels);
}
public BWImage(int width, int height, byte[] pixels) {
this.height = height;
this.width = width;
storage = makeStorage(width, height, pixels);
}
public BWImage(BWImage image) {
width = image.getWidth();
height = image.getHeight();
byte[] bytePixels = new byte[width*height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
bytePixels[y*width+x] = image.getByte(x, y);
storage = makeStorage(width, height, bytePixels);
}
public BWImage(RGBImage image) {
width = image.getWidth();
height = image.getHeight();
byte[] result = new byte[height*width];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
RGB rgb = image.getRGB(x, y);
result[y*width+x] = BWImage.toByte(rgb.getBrightness());
}
storage = makeStorage(width, height, result);
}
/*public BWImage(BufferedImage image) {
this(new RGBImage(image));
}*/
BWImage(BufferedImage image) { try {
width = image.getWidth();
height = image.getHeight();
int[] pixels = new int[width*height];
byte[] bytePixels = new byte[width*height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
if (!pixelGrabber.grabPixels())
throw fail("Could not grab pixels");
int n = width*height;
for (int i = 0; i < n; i++) {
//bytePixels[i] = pixelToByte(pixels[i]);
int packed = pixels[i];
float r = ((packed >> 16) & 0xFF)/255f;
float g = ((packed >> 8) & 0xFF)/255f;
float b = (packed & 0xFF)/255f;
bytePixels[i] = (byte) ((r+g+b)/3.0f*255f);
}
storage = makeStorage(width, height, bytePixels);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
// TODO: does it exactly match the other method? (asRGB+getBrightness+toByte)
static byte pixelToByte(int packed) {
/*int r = (packed >> 16) & 0xFF;
int g = (packed >> 8) & 0xFF;
int b = packed & 0xFF;
ret (byte) ((r+g+b)/3.0f);*/
float r = ((packed >> 16) & 0xFF)/255f;
float g = ((packed >> 8) & 0xFF)/255f;
float b = (packed & 0xFF)/255f;
return (byte) ((r+g+b)/3.0f*255f);
}
public byte getByte(int x, int y) {
return inRange(x, y) ? storage.getByte(x,y ) : toByte(borderColor);
}
public BWImage(int width, int height, float brightness) {
this.width = width;
this.height = height;
byte[] pixels = new byte[width*height];
for (int i = 0; i < pixels.length; i++)
pixels[i] = toByte(brightness);
storage = makeStorage(width, height, pixels);
}
public double averageBrightness() {
double sum = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
sum += getPixel(x, y);
return (sum/(double) (height*width));
}
public float minimumBrightness() {
float min = 1;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
min = Math.min(min, getPixel(x, y));
return min;
}
public float getPixel(int x, int y) {
return inRange(x, y) ? toFloat(storage.getByte(x,y )) : borderColor;
}
public static byte toByte(float pixel) {
return (byte) (pixel*255f);
}
public static float toFloat(byte pixel) {
return (((int) pixel) & 255)/255f;
}
private boolean inRange(int x, int y) {
return x >= 0 && x < width && y >= 0 && y < height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public RGBImage toRGB() {
RGB[] rgbs = new RGB[width*height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
float p = getPixel(x, y);
rgbs[y*width+x] = new RGB(p, p, p);
}
return new RGBImage(width, height, rgbs);
}
public BWImage clip(int x, int y, int w, int h) {
return clip(new Rectangle(x, y, w, h));
}
private Rectangle fixClipRect(Rectangle r) {
return r.intersection(new Rectangle(0, 0, width, height));
}
/** this should be multithread-safe */
public BWImage clip(Rectangle r) {
r = fixClipRect(r);
byte[] newPixels = new byte[r.height*r.width];
for (int y = 0; y < r.height; y++)
for (int x = 0; x < r.width; x++)
newPixels[y*r.width+x] = getByte(r.x+x, r.y+y);
return new BWImage(r.width, r.height, newPixels);
}
public void setPixel(int x, int y, float brightness) {
storage.setByte(x, y, toByte(fixPixel(brightness)));
}
public void setByte(int x, int y, byte brightness) {
storage.setByte(x, y, brightness);
}
private float fixPixel(float pixel) {
return Math.max(0, Math.min(1, pixel));
}
public float getBorderColor() {
return borderColor;
}
public void setBorderColor(float borderColor) {
this.borderColor = borderColor;
}
public boolean anyPixelBrighterThan(double threshold) {
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
if (getPixel(x, y) > threshold)
return true;
return false;
}
BufferedImage getBufferedImage() {
//ret toRGB().getBufferedImage();
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
int b = ((int) getByte(x, y) & 0xFF);
bufferedImage.setRGB(x, y, b*0x010101);
}
return bufferedImage;
}
byte[] getBytes() {
return storage.pixels;
}
}
static class BWImageSimpleStorage {
int width, height;
byte[] pixels;
// for unstructure()
BWImageSimpleStorage() {}
public BWImageSimpleStorage(int width, int height, byte[] pixels) {
this.width = width;
this.height = height;
this.pixels = pixels;
}
public void setByte(int x, int y, byte b) {
pixels[y*width+x] = b;
}
public byte getByte(int x, int y) {
return pixels[y*width+x];
}
}
static class Var {
A v; // you can access this directly if you use one thread
Var() {}
Var(A v) {
this.v = v;}
synchronized void set(A a) { v = a; }
synchronized A get() { return v; }
synchronized boolean has() { return v != null; }
}
// uses HashMap by default
static class MultiSet {
Map map = new HashMap();
public MultiSet(boolean useTreeMap) {
if (useTreeMap)
map = new TreeMap();
}
public MultiSet() {
}
public MultiSet(Collection c) {
addAll(c);
}
public void add(A key) {
add(key, 1);
}
public void addAll(Collection c) {
if (c != null) for (A a : c)
add(a);
}
public void add(A key, int count) {
if (map.containsKey(key))
map.put(key, map.get(key)+count);
else
map.put(key, count);
}
public int get(A key) {
return key != null && map.containsKey(key) ? map.get(key) : 0;
}
public boolean contains(A key) {
return map.containsKey(key);
}
public void remove(A key) {
Integer i = map.get(key);
if (i != null && i > 1)
map.put(key, i - 1);
else
map.remove(key);
}
public List getTopTen() {
return getTopTen(10);
}
public List getTopTen(int maxSize) {
List list = getSortedListDescending();
return list.size() > maxSize ? list.subList(0, maxSize) : list;
}
List highestFirst() {
return getSortedListDescending();
}
List lowestFirst() {
return reversedList(getSortedListDescending());
}
public List getSortedListDescending() {
List list = new ArrayList (map.keySet());
Collections.sort(list, new Comparator () {
public int compare(A a, A b) {
return map.get(b).compareTo(map.get(a));
}
});
return list;
}
public int getNumberOfUniqueElements() {
return map.size();
}
int uniqueSize() {
return map.size();
}
public Set asSet() {
return map.keySet();
}
Set keySet() { // synonym for idiots
return map.keySet();
}
public A getMostPopularEntry() {
int max = 0;
A a = null;
for (Map.Entry entry : map.entrySet()) {
if (entry.getValue() > max) {
max = entry.getValue();
a = entry.getKey();
}
}
return a;
}
public void removeAll(A key) {
map.remove(key);
}
public int size() {
int size = 0;
for (int i : map.values())
size += i;
return size;
}
public MultiSet mergeWith(MultiSet set) {
MultiSet result = new MultiSet ();
for (A a : set.asSet()) {
result.add(a, set.get(a));
}
return result;
}
public boolean isEmpty() {
return map.isEmpty();
}
public String toString() {
return structure(this);
}
public void clear() {
map.clear();
}
Map asMap() {
return cloneMap(map);
}
}
static class RGB {
public final float r, g, b;
public RGB(float r, float g, float b) {
this.r = r;
this.g = g;
this.b = b;
}
public RGB(double r, double g, double b) {
this.r = (float) r;
this.g = (float) g;
this.b = (float) b;
}
public RGB(double brightness) {
this.r = this.g = this.b = (float) brightness;
}
public RGB(Color color) {
this.r = color.getRed()/255f;
this.g = color.getGreen()/255f;
this.b = color.getBlue()/255f;
}
public RGB(String hex) {
r = Integer.parseInt(hex.substring(0, 2), 16)/255f;
g = Integer.parseInt(hex.substring(2, 4), 16)/255f;
b = Integer.parseInt(hex.substring(4, 6), 16)/255f;
}
public float getComponent(int i) {
return i == 0 ? r : i == 1 ? g : b;
}
public Color getColor() {
return new Color(r, g, b);
}
public static RGB newSafe(float r, float g, float b) {
return new RGB(Math.max(0, Math.min(1, r)), Math.max(0, Math.min(1, g)), Math.max(0, Math.min(1, b)));
}
public int asInt() {
return getColor().getRGB() & 0xFFFFFF;
}
public float getBrightness() {
return (r+g+b)/3.0f;
}
public String getHexString() {
return Integer.toHexString(asInt() | 0xFF000000).substring(2).toUpperCase();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RGB)) return false;
RGB rgb = (RGB) o;
if (Float.compare(rgb.b, b) != 0) return false;
if (Float.compare(rgb.g, g) != 0) return false;
if (Float.compare(rgb.r, r) != 0) return false;
return true;
}
@Override
public int hashCode() {
int result = (r != +0.0f ? Float.floatToIntBits(r) : 0);
result = 31 * result + (g != +0.0f ? Float.floatToIntBits(g) : 0);
result = 31 * result + (b != +0.0f ? Float.floatToIntBits(b) : 0);
return result;
}
public boolean isBlack() {
return r == 0f && g == 0f && b == 0f;
}
public boolean isWhite() {
return r == 1f && g == 1f && b == 1f;
}
public String toString() {
return getHexString();
}
}
static class RGBImage {
transient BufferedImage bufferedImage;
File file;
int width, height;
int[] pixels;
// color returned when getPixel is called with out-of-bounds position
int background = 0xFFFFFF;
RGBImage() {}
RGBImage(BufferedImage image) {
this(image, null);
}
RGBImage(BufferedImage image, File file) {
this.file = file;
bufferedImage = image;
width = image.getWidth();
height = image.getHeight();
pixels = new int[width*height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
try {
if (!pixelGrabber.grabPixels())
throw new RuntimeException("Could not grab pixels");
cleanPixels(); // set upper byte to 0
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/** We assume it's a file name to load from */
RGBImage(String file) throws IOException {
this(new File(file));
}
RGBImage(Dimension size, Color color) {
this(size.width, size.height, color);
}
RGBImage(Dimension size, RGB color) {
this(size.width, size.height, color);
}
private void cleanPixels() {
for (int i = 0; i < pixels.length; i++)
pixels[i] &= 0xFFFFFF;
}
RGBImage(int width, int height, int[] pixels) {
this.width = width;
this.height = height;
this.pixels = pixels;
}
RGBImage(int w, int h, RGB[] pixels) {
this.width = w;
this.height = h;
this.pixels = asInts(pixels);
}
public static int[] asInts(RGB[] pixels) {
int[] ints = new int[pixels.length];
for (int i = 0; i < pixels.length; i++)
ints[i] = pixels[i] == null ? 0 : pixels[i].getColor().getRGB();
return ints;
}
public RGBImage(int w, int h) {
this(w, h, Color.black);
}
RGBImage(int w, int h, RGB rgb) {
this.width = w;
this.height = h;
this.pixels = new int[w*h];
int col = rgb.asInt();
if (col != 0)
for (int i = 0; i < pixels.length; i++)
pixels[i] = col;
}
RGBImage(RGBImage image) {
this(image.width, image.height, copyPixels(image.pixels));
}
RGBImage(int width, int height, Color color) {
this(width, height, new RGB(color));
}
RGBImage(File file) throws IOException {
this(javax.imageio.ImageIO.read(file));
}
private static int[] copyPixels(int[] pixels) {
int[] copy = new int[pixels.length];
System.arraycopy(pixels, 0, copy, 0, pixels.length);
return copy;
}
public int getIntPixel(int x, int y) {
if (inRange(x, y))
return pixels[y * width + x];
else
return background;
}
public static RGB asRGB(int packed) {
int r = (packed >> 16) & 0xFF;
int g = (packed >> 8) & 0xFF;
int b = packed & 0xFF;
return new RGB(r / 255f, g / 255f, b / 255f);
}
public RGB getRGB(int x, int y) {
if (inRange(x, y))
return asRGB(pixels[y * width + x]);
else
return new RGB(background);
}
/** alias of getRGB - I kept typing getPixel instead of getRGB all the time, so I finally created it */
public RGB getPixel(int x, int y) {
return getRGB(x, y);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
/** Attention: cached, i.e. does not change when image itself changes */
/** @NotNull */
public BufferedImage getBufferedImage() {
if (bufferedImage == null) {
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//bufferedImage.setData(Raster.createRaster(new SampleModel()));
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
bufferedImage.setRGB(x, y, pixels[y*width+x]);
}
return bufferedImage;
}
public RGBImage clip(Rectangle r) {
r = fixClipRect(r);
int[] newPixels;
try {
newPixels = new int[r.width*r.height];
} catch (RuntimeException e) {
System.out.println(r);
throw e;
}
for (int y = 0; y < r.height; y++) {
System.arraycopy(pixels, (y+r.y)*width+r.x, newPixels, y*r.width, r.width);
}
return new RGBImage(r.width, r.height, newPixels);
}
private Rectangle fixClipRect(Rectangle r) {
r = r.intersection(new Rectangle(0, 0, width, height));
if (r.isEmpty())
r = new Rectangle(r.x, r.y, 0, 0);
return r;
}
public File getFile() {
return file;
}
/** can now also do GIF (not just JPEG) */
public static RGBImage load(String fileName) {
return load(new File(fileName));
}
/** can now also do GIF (not just JPEG) */
public static RGBImage load(File file) {
try {
BufferedImage bufferedImage = javax.imageio.ImageIO.read(file);
return new RGBImage(bufferedImage);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public int getInt(int x, int y) {
return pixels[y * width + x];
}
public void save(File file) throws IOException {
String name = file.getName().toLowerCase();
String type;
if (name.endsWith(".png")) type = "png";
else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) type = "jpeg";
else throw new IOException("Unknown image extension: " + name);
javax.imageio.ImageIO.write(getBufferedImage(), type, file);
}
public static RGBImage dummyImage() {
return new RGBImage(1, 1, new int[] {0xFFFFFF});
}
public int[] getPixels() {
return pixels;
}
public void setPixel(int x, int y, RGB rgb) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = rgb.asInt();
}
public void setPixel(int x, int y, Color color) {
setPixel(x, y, new RGB(color));
}
public void setPixel(int x, int y, int rgb) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = rgb;
}
public RGBImage copy() {
return new RGBImage(this);
}
public boolean inRange(int x, int y) {
return x >= 0 && y >= 0 && x < width && y < height;
}
public int getBackground() {
return background;
}
public void setBackground(int background) {
this.background = background;
}
public Dimension getSize() {
return new Dimension(width, height);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RGBImage rgbImage = (RGBImage) o;
if (height != rgbImage.height) return false;
if (width != rgbImage.width) return false;
if (!Arrays.equals(pixels, rgbImage.pixels)) return false;
return true;
}
@Override
public int hashCode() {
int result = width;
result = 31 * result + height;
result = 31 * result + Arrays.hashCode(pixels);
return result;
}
public String getHex(int x, int y) {
return getPixel(x, y).getHexString();
}
public RGBImage clip(int x, int y, int width, int height) {
return clip(new Rectangle(x, y, width, height));
}
public RGBImage clipLine(int y) {
return clip(0, y, width, 1);
}
public int numPixels() {
return width*height;
}
}
static boolean bwRawImageSearch_verbose;
static BWImageSectionComparator bwRawImageSearch_comparator;
static int bwRawImageSearch_maxEntries = 1000;
// similarity = e.g. 0.99f
static List bwRawImageSearch(BWImage big, BWImage pat, float similarity) {
List found = new ArrayList();
int wp = pat.getWidth(), hp = pat.getHeight();
int w = big.getWidth(), h = big.getHeight();
float maxError = (1f-similarity)*wp*hp;
for (int y = 0; y < h-hp; y++)
for (int x = 0; x < w-wp; x++) {
float diff = bwRawImageSearch_comparator != null
? bwRawImageSearch_comparator.compare(big, pat, x, y, maxError)
: bwImageSectionsSimilarity(big, pat, x, y, maxError);
if (diff <= maxError) {
float sim = 1-diff/(wp*hp);
if (bwRawImageSearch_verbose)
print(" Image found at " + x + "/" + y + " [sim: " + formatDouble(sim, 4) + "]");
Rect r = new Rect(x, y, wp, hp);
found.add(new FoundImg(r, sim));
ping();
if (l(found) >= bwRawImageSearch_maxEntries) return found;
x += wp-1;
}
}
return found;
}
static List reversedList(Collection l) {
List x = cloneList(l);
Collections.reverse(x);
return x;
}
static volatile boolean licensed_yes = true;
static boolean licensed() {
ping();
return licensed_yes;
}
static void licensed_off() {
licensed_yes = false;
}
static void addAll(Collection c, Collection b) {
c.addAll(b);
}
static void addAll(Collection c, Object[] b) {
c.addAll(Arrays.asList(b));
}
static float bwImageSectionsSimilarity(BWImage big, BWImage pat, int x, int y, float max) {
int wp = pat.getWidth(), hp = pat.getHeight();
int w = big.getWidth(), h = big.getHeight();
float diff = 0;
for (int yy = 0; yy < hp; yy++)
for (int xx = 0; xx < wp; xx++) {
diff += abs(big.getPixel(x+xx, y+yy)-pat.getPixel(xx, yy));
if (diff > max) return max+1;
}
return diff;
}
static int hashCode(Object a) {
return a == null ? 0 : a.hashCode();
}
static BufferedImage clipBufferedImage(BufferedImage src, Rectangle clip) {
return src.getSubimage(clip.x, clip.y, clip.width, clip.height);
}
static A findConcept(Class c, Object... params) {
return findConceptWhere(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(Collection l) {
TreeSet set = new TreeSet();
for (String o : l)
if (o != null)
set.add(o);
return set;
}
static List filter(Iterable c, Object pred) {
List x = new ArrayList();
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 A uniq(Class c, Object... params) {
return uniqueConcept(c, params);
}
static boolean inRange(int x, int n) {
return x >= 0 && x < n;
}
static int asInt(Object o) {
return toInt(o);
}
static List reversed(Collection l) {
return reversedList(l);
}
static A uniqueConcept(Class c, Object... params) {
params = expandParams(c, params);
A x = findConceptWhere(c, params);
if (x == null) {
x = nuObject(c);
for (int i = 0; i+1 < l(params); i += 2)
cset(x, (String) params[i], params[i+1]);
}
return x;
}
public static String formatDouble(double d, int digits) {
String format = "0.";
for (int i = 0; i < digits; i++) format += "#";
return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d);
}
static float abs(float f) {
return Math.abs(f);
}
static A findConceptWhere(Class c, Object... params) {
params = expandParams(c, params);
for (A x : list(c))
if (checkConceptFields(x, params))
return x;
return null;
}
static int toInt(Object o) {
if (o == null) return 0;
if (o instanceof Number)
return ((Number) o).intValue();
if (o instanceof String)
return parseInt((String) o);
throw fail("woot not int: " + getClassName(o));
}
static int toInt(long l) {
if (l != (int) l) throw fail("Too large for int: " + l);
return (int) l;
}
static interface BWImageSectionComparator {
float compare(BWImage big, BWImage pat, int x, int y, float max);
}
static boolean stdEq2(Object a, Object b) {
if (a == null) return b == null;
if (b == null) return false;
if (a.getClass() != b.getClass()) return false;
for (String field : allFields(a))
if (neq(getOpt(a, field), getOpt(b, field)))
return false;
return true;
}
static int stdHash2(Object a) {
if (a == null) return 0;
return stdHash(a, toStringArray(allFields(a)));
}
static String[] toStringArray(Collection c) {
String[] a = new String[l(c)];
Iterator it = c.iterator();
for (int i = 0; i < l(a); i++)
a[i] = it.next();
return a;
}
static String[] toStringArray(Object o) {
if (o instanceof String[])
return (String[]) o;
else if (o instanceof Collection)
return toStringArray((Collection) o);
else
throw fail("Not a collection or array: " + structure(o));
}
static Set allFields(Object o) {
TreeSet fields = new TreeSet();
Class _c = _getClass(o);
do {
for (Field f : _c.getDeclaredFields())
fields.add(f.getName());
_c = _c.getSuperclass();
} while (_c != null);
return fields;
}
static int stdHash(Object a, String... fields) {
if (a == null) return 0;
int hash = getClassName(a).hashCode();
for (String field : fields)
hash = hash*2+hashCode(getOpt(a, field));
return hash;
}
}