import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import java.util.function.*;
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 java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
import java.time.Duration;
import java.lang.invoke.VarHandle;
import java.lang.invoke.MethodHandles;
import java.text.NumberFormat;
import static x30_pkg.x30_util.DynamicObject;
import java.awt.geom.*;
import java.text.*;
import java.util.TimeZone;
import java.nio.file.Path;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
class main {
static class G22PixelSplitMasks implements IG22OptimizedMasksHolder {
G22PixelSplitMasks() {}
final public G22PixelSplitMasks setSplitPixel(Pt splitPixel){ return splitPixel(splitPixel); }
public G22PixelSplitMasks splitPixel(Pt splitPixel) { this.splitPixel = splitPixel; return this; } final public Pt getSplitPixel(){ return splitPixel(); }
public Pt splitPixel() { return splitPixel; }
Pt splitPixel;
final public G22PixelSplitMasks setDarkHolder(IG22MasksHolder darkHolder){ return darkHolder(darkHolder); }
public G22PixelSplitMasks darkHolder(IG22MasksHolder darkHolder) { this.darkHolder = darkHolder; return this; } final public IG22MasksHolder getDarkHolder(){ return darkHolder(); }
public IG22MasksHolder darkHolder() { return darkHolder; }
IG22MasksHolder darkHolder;
final public G22PixelSplitMasks setBrightHolder(IG22MasksHolder brightHolder){ return brightHolder(brightHolder); }
public G22PixelSplitMasks brightHolder(IG22MasksHolder brightHolder) { this.brightHolder = brightHolder; return this; } final public IG22MasksHolder getBrightHolder(){ return brightHolder(); }
public IG22MasksHolder brightHolder() { return brightHolder; }
IG22MasksHolder brightHolder;
// for search - how much the "correct" branch is preferred
final public G22PixelSplitMasks setBias(double bias){ return bias(bias); }
public G22PixelSplitMasks bias(double bias) { this.bias = bias; return this; } final public double getBias(){ return bias(); }
public double bias() { return bias; }
double bias = 0.9;
public List> masks() {
return new ConcatOnDemandList(
darkHolder.masks(),
brightHolder.masks());
}
public List> subHolders() {
return ll(darkHolder, brightHolder);
}
public void transformSubHolders(IF1, IG22MasksHolder> f) {
darkHolder = f.get(darkHolder);
brightHolder = f.get(brightHolder);
}
@Override
public PStackComputable findSimilarMasks(G22FindSimilarMasksTask task) {
return new FindSimilarMasks(task);
}
class FindSimilarMasks extends PStackComputableWithStep implements IMakeEmptyClone , IFieldsToList{
G22FindSimilarMasksTask task;
FindSimilarMasks() {}
FindSimilarMasks(G22FindSimilarMasksTask task) {
this.task = task;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + task + ")"; }public Object[] _fieldsToList() { return new Object[] {task}; }
boolean brightBranch = false;
public FindSimilarMasks makeEmptyClone() { return new FindSimilarMasks(); }
void step(IPStack stack) {
if (step == 0) {
++step;
boolean bright = isMaskBright(task.queryImage);
printVars("step 0", "splitPixel", splitPixel, "bright", bright);
stack.probabilisticOptions(this, ll(
withProbability(1.0, self -> self.brightBranch = bright),
withProbability(1-bias, self -> self.brightBranch = !bright)));
} else {
printVars("step 1", "splitPixel", splitPixel, "brightBranch", brightBranch);
IG22MasksHolder branch = brightBranch ? brightHolder : darkHolder;
stack.tailCall(branch.findSimilarMasks(task));
}
}
}
// Does the mask belong in darkHolder or brightHolder?
boolean isMaskBright(Image2B maskImage) {
return maskImage.getBoolPixel(splitPixel);
}
public IG22MasksHolder cloneTreeWithLabelTransform(IF1 f) {
return new G22PixelSplitMasks().splitPixel(splitPixel)
.darkHolder(darkHolder.cloneTreeWithLabelTransform(f))
.brightHolder(brightHolder.cloneTreeWithLabelTransform(f));
}
final public G22PixelSplitMasks setMaskSize(WidthAndHeight maskSize){ return maskSize(maskSize); }
public G22PixelSplitMasks maskSize(WidthAndHeight maskSize) { this.maskSize = maskSize; return this; } final public WidthAndHeight getMaskSize(){ return maskSize(); }
public WidthAndHeight maskSize() { return maskSize; }
WidthAndHeight maskSize;
//new MultiSet labels;
// default mask size
{ maskSize(g22defaultMaskSideLength()); }
G22PixelSplitMasks maskSize(int size) {
return maskSize(widthAndHeight(size));
}
Image2B regionToMaskImage(IImageRegion region) {
return toImage2B(scaledIBinaryImage(maskSize, regionToIBinaryImage(region)));
}
public List maskImages() {
return map(masks(), mask -> mask.image());
}
BufferedImage masksSquare() {
return mergeBufferedImagesAsSquare(allToBufferedImage(maskImages()));
}
PatchworkImage> masksPatchworkSquare() {
return patchworkImagesAsSquare(map(masks(), mask -> pair(toBufferedImage(mask.image()), mask)));
}
public String toString() {
return renderVars(shortClassName(this), "maskSize", maskSize, "masks" , n2(masks()));
}
public G22GhostImage ghost_cache;
public G22GhostImage ghost() { if (ghost_cache == null) ghost_cache = ghost_load(); return ghost_cache;}
public G22GhostImage ghost_load() {
return new G22GhostImage(maskImages());
}
public Double certainty_cache;
public double certainty() { if (certainty_cache == null) certainty_cache = certainty_load(); return certainty_cache;}
public double certainty_load() {
return ghost().certainty();
}
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static String shortClassName_dropNumberPrefix(Object o) {
return dropNumberPrefix(shortClassName(o));
}
// Use like this: printVars(+x, +y);
// Or: printVars("bla", +x);
// Or: printVars bla(, +x);
static void printVars(Object... params) {
printVars_str(params);
}
static WithProbability withProbability(double probability, A a) {
return new WithProbability(probability, a);
}
static List> withProbability(IF1 makeProbability, Iterable l) {
return map(a -> withProbability(makeProbability.get(a), a), l);
}
static IF0 g22defaultMaskSideLength;
static int g22defaultMaskSideLength() { return g22defaultMaskSideLength != null ? g22defaultMaskSideLength.get() : g22defaultMaskSideLength_base(); }
final static int g22defaultMaskSideLength_fallback(IF0 _f) { return _f != null ? _f.get() : g22defaultMaskSideLength_base(); }
static int g22defaultMaskSideLength_base() {
return 32;
}
static WidthAndHeight widthAndHeight(BufferedImage image) {
return image == null ? null : widthAndHeight(image.getWidth(), image.getHeight());
}
static WidthAndHeight widthAndHeight(int w) { return widthAndHeight(w, w); }
static WidthAndHeight widthAndHeight(int w, int h) {
return new WidthAndHeightFinal(w, h);
}
static Image2B toImage2B(BufferedImage img) {
return img == null ? null : new Image2B(img);
}
static Image2B toImage2B(MakesBufferedImage img) {
if (img == null) return null;
if (img instanceof Image2B) return ((Image2B) img);
if (img instanceof BWImage) return new Image2B((BWImage) img);
if (img instanceof IBinaryImage) return iBinaryImageToImage2B((IBinaryImage) img);
return new Image2B(toBufferedImage(img));
}
static IBinaryImage scaledIBinaryImage(WidthAndHeight size, IBinaryImage img) {
return scaledIBinaryImage(size.w(), size.h(), img);
}
static IBinaryImage scaledIBinaryImage(int w, IBinaryImage img) { return scaledIBinaryImage(w, widthToHeight(w, img), img); }
static IBinaryImage scaledIBinaryImage(int w, int h, IBinaryImage img) {
if (img == null) return null;
int w1 = img.getWidth(), h1 = img.getHeight();
if (w == w1 && h == h1) return img;
double factorX = doubleRatio(w1, w);
double factorY = doubleRatio(h1, h);
return iBinaryImageFromFunction(w, h,
(x, y) -> img.getBoolPixel(ifloor(x*factorX), ifloor(y*factorY)));
}
static IBinaryImage regionToIBinaryImage(IImageRegion region) {
Rect r = region.bounds();
return iBinaryImageFromFunction(r.w, r.h,
(x, y) -> !region.contains(r.x+x, r.y+y));
}
static List map(Iterable l, Object f) { return map(f, l); }
static List map(Object f, Iterable l) {
List x = emptyList(l);
if (l != null) for (Object o : l)
{ ping(); x.add(callF(f, o)); }
return x;
}
// map: func(key, value) -> list element
static List map(Map map, Object f) {
List x = new ArrayList();
if (map != null) for (Object _e : map.entrySet()) { ping();
Map.Entry e = (Map.Entry) _e;
x.add(callF(f, e.getKey(), e.getValue()));
}
return x;
}
static List map(Object f, Object[] l) { return map(f, asList(l)); }
static List map(Object[] l, Object f) { return map(f, l); }
static List map(Object f, Map map) {
return map(map, f);
}
static List map(Iterable l, F1 f) { return map(f, l); }
static List map(F1 f, Iterable l) {
List x = emptyList(l);
if (l != null) for (A o : l)
{ ping(); x.add(callF(f, o)); }
return x;
}
static List map(IF1 f, Iterable l) { return map(l, f); }
static List map(Iterable l, IF1 f) {
List x = emptyList(l);
if (l != null) {
var it = l.iterator();
if (it.hasNext()) {
var pingSource = pingSource();
do {
ping(pingSource);
x.add(f.get(it.next()));
} while (it.hasNext());
}
}
return x;
}
static List map(IF1 f, A[] l) { return map(l, f); }
static List map(A[] l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
{ ping(); x.add(f.get(o)); }
return x;
}
static List map(Map map, IF2 f) {
List x = new ArrayList();
if (map != null) for (Map.Entry e : map.entrySet()) { ping();
x.add(f.get(e.getKey(), e.getValue()));
}
return x;
}
// new magic alias for mapLL - does it conflict?
static List map(IF1 f, A data1, A... moreData) {
List x = emptyList(l(moreData)+1);
x.add(f.get(data1));
if (moreData != null) for (A o : moreData)
{ ping(); x.add(f.get(o)); }
return x;
}
static BufferedImage mergeBufferedImagesAsSquare(Iterable l) {
return mergeBufferedImagesVH(listToSquareishChunks(asList(l)));
}
static List allToBufferedImage(Iterable l) {
return map(__19 -> toBufferedImage(__19), l);
}
static PatchworkImage patchworkImagesAsSquare(Iterable> l) {
return patchworkImagesVH(listToSquareishChunks(asList(l)));
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static BufferedImage toBufferedImage(Object o) {
return toBufferedImageOpt(o);
}
// Use like this: renderVars(+x, +y)
// Or like this: renderVars SomeID(+x, +y)
static String renderVars(Object... params) {
return renderVars_str(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 String n2(long l) { return formatWithThousands(l); }
static String n2(AtomicLong l) { return n2(l.get()); }
static String n2(Collection l) { return n2(l(l)); }
static String n2(Map map) { return n2(l(map)); }
static String n2(double l, String singular) {
return empty(singular) ? str(l) : n2(l, singular, singular + "s");
}
static String n2(double l, String singular, String plural) {
if (fraction(l) == 0)
return n2((long) l, singular, plural);
else
return l + " " + plural;
}
static String n2(long l, String singular, String plural) {
return n_fancy2(l, singular, plural);
}
static String n2(long l, String singular) {
return empty(singular) ? n2(l) : n_fancy2(l, singular, singular + "s");
}
static String n2(Collection l, String singular) {
return n2(l(l), singular);
}
static String n2(Collection l, String singular, String plural) {
return n_fancy2(l, singular, plural);
}
static String n2(Map m, String singular, String plural) {
return n_fancy2(m, singular, plural);
}
static String n2(Map m, String singular) {
return n2(l(m), singular);
}
static String n2(long[] a, String singular) { return n2(l(a), singular); }
static String n2(Object[] a, String singular) { return n2(l(a), singular); }
static String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); }
static String n2(MultiSet ms, String singular) { return n2(ms, singular, singular + "s"); }
static String n2(MultiSet ms, String singular, String plural) {
return n_fancy2(ms, singular, plural);
}
static String n2(IMultiMap mm, String singular) { return n2(mm, singular, singular + "s"); }
static String n2(IMultiMap mm, String singular, String plural) {
return n_fancy2(l(mm), singular, plural);
}
static String dropNumberPrefix(String s) {
return dropFirst(s, indexOfNonDigit(s));
}
// Use like this: printVars_str(+x, +y);
// Or: printVars("bla", +x);
// Or: printVars bla(+x);
static void printVars_str(Object... params) {
print(renderVars_str(params));
}
static Image2B iBinaryImageToImage2B(IBinaryImage img) {
if (img == null) return null;
if (img instanceof Image2B) return ((Image2B) img);
int w = img.getWidth(), h = img.getHeight();
byte[] pixels = new byte[(w*h+7)/8];
int i = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
if (img.getBoolPixel(x, y))
pixels[i/8] |= 1 << (i & 7);
i++;
}
return new Image2B(w, h, pixels);
}
static int widthToHeight(int w, int h, int newWidth) {
return heightForWidth(w, h, newWidth);
}
static int widthToHeight(BufferedImage img, int newWidth) {
return heightForWidth(img.getWidth(), img.getHeight(), newWidth);
}
static int widthToHeight(int newWidth, BufferedImage img) {
return widthToHeight(img, newWidth);
}
static int widthToHeight(WidthAndHeight img, int newWidth) {
return heightForWidth(img.getWidth(), img.getHeight(), newWidth);
}
static int widthToHeight(int newWidth, WidthAndHeight img) {
return widthToHeight(img, newWidth);
}
static double doubleRatio(double x, double y) {
return y == 0 ? 0 : x/y;
}
static double doubleRatio(Seconds x, Seconds y) {
return doubleRatio(x.get(), y.get());
}
static IBinaryImage iBinaryImageFromFunction(IIntIntPred f, int w, int h) {
return new IBinaryImage() {
public int getWidth() { return w; }
public int getHeight() { return h; }
public boolean getBoolPixel(int x, int y) {
return f.get(x, y);
}
};
}
static IBinaryImage iBinaryImageFromFunction(int w, int h, IIntIntPred f) {
return iBinaryImageFromFunction(f, w, h);
}
static int ifloor(double d) {
return (int) Math.floor(d);
}
static IntRange ifloor(DoubleRange r) {
return r == null ? null : intRange(ifloor(r.start), ifloor(r.end));
}
static ArrayList emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
// get correct type at once
static ArrayList emptyList(Class c) {
return new ArrayList();
}
// legacy mode
//sbool ping_actions_shareable = true;
static volatile boolean ping_pauseAll = false;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions = false;
static Map ping_actions = newWeakHashMap();
static ThreadLocal ping_isCleanUpThread = new ThreadLocal();
// ignore pingSource if not PingV3
static boolean ping(PingSource pingSource) { return ping(); }
// always returns true
static boolean ping() {
//ifdef useNewPing
newPing();
//endifdef
if (ping_pauseAll || ping_anyActions) ping_impl(true /* XXX */);
//ifndef LeanMode ping_impl(); endifndef
return true;
}
// returns true when it slept
static boolean ping_impl(boolean okInCleanUp) { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) { // don't allow sharing ping_actions
if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get()))
failIfUnlicensed();
Object action = null;
synchronized(ping_actions) {
if (!ping_actions.isEmpty()) {
action = ping_actions.get(currentThread());
if (action instanceof Runnable)
ping_actions.remove(currentThread());
if (ping_actions.isEmpty()) ping_anyActions = false;
}
}
if (action instanceof Runnable)
((Runnable) action).run();
else if (eq(action, "cancelled"))
throw fail("Thread cancelled.");
}
return false;
} catch (Exception __e) { throw rethrow(__e); } }
static Map> callF_cache = newDangerousWeakHashMap();
static A callF(F0 f) {
return f == null ? null : f.get();
}
static B callF(F1 f, A a) {
return f == null ? null : f.get(a);
}
static A callF(IF0 f) {
return f == null ? null : f.get();
}
static B callF(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF(A a, IF1 f) {
return f == null ? null : f.get(a);
}
static C callF(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF(VF1 f, A a) {
if (f != null) f.get(a);
}
static void callF(A a, IVF1 f) {
if (f != null) f.get(a);
}
static void callF(IVF1 f, A a) {
if (f != null) f.get(a);
}
static Object callF(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF(Object f, Object... args) {
return safeCallF(f, args);
}
static Object safeCallF(Object f, Object... args) {
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
}
if (f == null) return null;
Class c = f.getClass();
ArrayList methods;
synchronized(callF_cache) {
methods = callF_cache.get(c);
if (methods == null)
methods = callF_makeCache(c);
}
int n = l(methods);
if (n == 0) {
if (f instanceof String)
throw fail("Legacy call: " + f);
throw fail("No get method in " + getClassName(c));
}
if (n == 1) return invokeMethod(methods.get(0), f, args);
for (int i = 0; i < n; i++) {
Method m = methods.get(i);
if (call_checkArgs(m, args, false))
return invokeMethod(m, f, args);
}
throw fail("No matching get method in " + getClassName(c));
}
// used internally
static ArrayList callF_makeCache(Class c) {
ArrayList l = new ArrayList();
Class _c = c;
do {
for (Method m : _c.getDeclaredMethods())
if (m.getName().equals("get")) {
makeAccessible(m);
l.add(m);
}
if (!l.isEmpty()) break;
_c = _c.getSuperclass();
} while (_c != null);
callF_cache.put(c, l);
return l;
}
// unclear semantics as to whether return null on null
static ArrayList asList(A[] a) {
return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a));
}
static ArrayList asList(byte[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (var i : a) l.add(i);
return l;
}
static ArrayList asList(int[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (int i : a) l.add(i);
return l;
}
static ArrayList asList(long[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (long i : a) l.add(i);
return l;
}
static ArrayList asList(float[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (float i : a) l.add(i);
return l;
}
static ArrayList asList(double[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (double i : a) l.add(i);
return l;
}
static ArrayList asList(short[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (short i : a) l.add(i);
return l;
}
static ArrayList asList(Iterator it) {
ArrayList l = new ArrayList();
if (it != null)
while (it.hasNext())
l.add(it.next());
return l;
}
// disambiguation
static ArrayList asList(IterableIterator s) {
return asList((Iterator) s);
}
static ArrayList asList(Iterable s) {
if (s instanceof ArrayList) return (ArrayList) s;
ArrayList l = new ArrayList();
if (s != null)
for (A a : s)
l.add(a);
return l;
}
static ArrayList asList(Producer p) {
ArrayList l = new ArrayList();
A a;
if (p != null) while ((a = p.next()) != null)
l.add(a);
return l;
}
static ArrayList asList(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
static ArrayList asList(ReverseChain c) {
return c == null ? emptyList() : c.toList();
}
static List asList(Pair p) {
return p == null ? null : ll(p.a, p.b);
}
// assumptions:
// -pingSource() stays constant within a stack frame (so you can cache it)
// -all changes happen with tempSetPingSource
// -multiple threads can share a PingSource
static PingSource pingSource() {
return pingSource_tl().get();
}
static PingSource pingSource(Thread thread) {
return pingSource_tl().get(thread);
}
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); }
static int l(IMultiMap mm) { return mm == null ? 0 : mm.size(); }
static int l(IntRange r) { return r == null ? 0 : r.length(); }
static double l(DoubleRange r) { return r == null ? 0 : r.length(); }
static int l(LongBuffer b) { return b == null ? 0 : b.size(); }
static int l(IntSize o) { return o == null ? 0 : o.size(); }
static BufferedImage mergeBufferedImagesVH(Collection> l) {
return mergeBufferedImagesVertically(map(__20 -> mergeBufferedImagesHorizontally(__20), l));
}
static List> listToSquareishChunks(List l) {
int chunkSize = max(1, iround(sqrt(l(l))));
return listToChunks(l, chunkSize);
}
static PatchworkImage patchworkImagesVH(Collection>> l) {
return mergePatchworkImagesVertically(map(__21 -> patchworkBufferedImagesHorizontally(__21), l));
}
static BufferedImage toBufferedImageOpt(Object o) {
if (o instanceof BufferedImage) return ((BufferedImage) o);
if (o instanceof Image) return copyImage((Image) o);
if (o instanceof MakesBufferedImage)
return ((MakesBufferedImage) o).getBufferedImage();
String c = getClassName(o);
// Keep this because it also works on imported objects
if (eqOneOf(c, "main$BWImage", "main$RGBImage"))
return (BufferedImage) call(o, "getBufferedImage");
return null;
}
// Use like this: renderVars(+x, +y)
// Or like this: renderVars("bla", +x, +y)
static String renderVars_str(Object... params) {
List l = new ArrayList();
int i = 0;
if (odd(l(params))) {
l.add(strOrNull(first(params)));
++i;
}
for (; i+1 < l(params); i += 2)
l.add(params[i] + "=" + params[i+1]);
return trim(joinWithComma(l));
}
static String shortenClassName(String name) {
if (name == null) return null;
int i = lastIndexOf(name, "$");
if (i < 0) i = lastIndexOf(name, ".");
return i < 0 ? name : substring(name, i+1);
}
static String formatWithThousands(long l) {
return formatWithThousandsSeparator(l);
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(BitSet bs) { return bs == null || bs.isEmpty(); }
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
if (o instanceof byte[]) return empty((byte[]) o);
if (o == null) return true;
throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); }
static boolean empty(IMultiMap mm) { return mm == null || mm.size() == 0; }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(IntRange r) { return r == null || r.empty(); }
static boolean empty(DoubleRange r) { return r == null || r.isEmpty(); }
static boolean empty(LongBuffer b) { return b == null || b.isEmpty(); }
static boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); }
static boolean empty(Chain c) { return c == null; }
static boolean empty(AppendableChain c) { return c == null; }
static String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static String str(char[] c, int offset, int count) {
return new String(c, offset, count);
}
static double fraction(double d) {
return d % 1;
}
static String n_fancy2(long l, String singular, String plural) {
return formatWithThousandsSeparator(l) + " " + trim(l == 1 ? singular : plural);
}
static String n_fancy2(Collection l, String singular, String plural) {
return n_fancy2(l(l), singular, plural);
}
static String n_fancy2(Map m, String singular, String plural) {
return n_fancy2(l(m), singular, plural);
}
static String n_fancy2(Object[] a, String singular, String plural) {
return n_fancy2(l(a), singular, plural);
}
static String n_fancy2(MultiSet ms, String singular, String plural) {
return n_fancy2(l(ms), singular, plural);
}
static String[] dropFirst(int n, String[] a) {
return drop(n, a);
}
static String[] dropFirst(String[] a) {
return drop(1, a);
}
static Object[] dropFirst(Object[] a) {
return drop(1, a);
}
static List dropFirst(List l) {
return dropFirst(1, l);
}
static List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); }
static List dropFirst(Iterable i) { return dropFirst(toList(i)); }
static List dropFirst(int n, List l) {
return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size()));
}
static List dropFirst(List l, int n) {
return dropFirst(n, l);
}
static String dropFirst(int n, String s) { return substring(s, n); }
static String dropFirst(String s, int n) { return substring(s, n); }
static String dropFirst(String s) { return substring(s, 1); }
static Chain dropFirst(Chain c) {
return c == null ? null : c.next;
}
static int indexOfNonDigit(String s) {
int n = l(s);
for (int i = 0; i < n; i++)
if (!isDigit(s.charAt(i)))
return i;
return -1;
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static boolean printAlsoToSystemOut = true;
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal