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;
// a point in a ticker sequence
import java.text.*;
import java.text.NumberFormat;
import java.util.TimeZone;
import java.awt.geom.*;
import static x30_pkg.x30_util.DynamicObject;
class main {
static class TickerPoint implements IFieldsToList{
TickerSequence ticker;
long currentTime;
TickerPoint() {}
TickerPoint(TickerSequence ticker, long currentTime) {
this.currentTime = currentTime;
this.ticker = ticker;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + ticker + ", " + currentTime + ")"; }public Object[] _fieldsToList() { return new Object[] {ticker, currentTime}; }
double currentPrice() { return lookback(0); }
// time = ms to look back
double lookback(long time) {
return ticker.priceAtTimestamp(currentTime-time);
}
// false if looking back would require going outside of the time range
boolean canLookback(long time) {
return currentTime-time >= ticker.startTime();
}
}
static String shortClassName_dropNumberPrefix(Object o) {
return dropNumberPrefix(shortClassName(o));
}
static String dropNumberPrefix(String s) {
return dropFirst(s, indexOfNonDigit(s));
}
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[] 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 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[] drop(int n, String[] a) {
n = Math.min(n, a.length);
String[] b = new String[a.length-n];
System.arraycopy(a, n, b, 0, b.length);
return b;
}
static Object[] drop(int n, Object[] a) {
n = Math.min(n, a.length);
Object[] b = new Object[a.length-n];
System.arraycopy(a, n, b, 0, b.length);
return b;
}
static ArrayList toList(A[] a) { return asList(a); }
static ArrayList toList(int[] a) { return asList(a); }
static ArrayList toList(short[] a) { return asList(a); }
static ArrayList toList(long[] a) { return asList(a); }
static ArrayList toList(Set s) { return asList(s); }
static ArrayList toList(Iterable s) { return asList(s); }
static String substring(String s, int x) {
return substring(s, x, strL(s));
}
static String substring(String s, int x, int y) {
if (s == null) return null;
if (x < 0) x = 0;
int n = s.length();
if (y < x) y = x;
if (y > n) y = n;
if (x >= y) return "";
return s.substring(x, y);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
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(IMultiMap mm) { return mm == null ? 0 : mm.size(); }
static int l(LongBuffer b) { return b == null ? 0 : b.size(); }
static int l(IntSize o) { return o == null ? 0 : o.size(); }
static boolean isDigit(char c) {
return Character.isDigit(c);
}
static int lastIndexOf(String a, String b) {
return a == null || b == null ? -1 : a.lastIndexOf(b);
}
static int lastIndexOf(String a, char b) {
return a == null ? -1 : a.lastIndexOf(b);
}
// starts searching from i-1
static int lastIndexOf(List l, int i, A a) {
if (l == null) return -1;
for (i = min(l(l), i)-1; i >= 0; i--)
if (eq(l.get(i), a))
return i;
return -1;
}
static int lastIndexOf(List l, A a) {
if (l == null) return -1;
for (int i = l(l)-1; i >= 0; i--)
if (eq(l.get(i), a))
return i;
return -1;
}
// 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(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);
}
static int strL(String s) {
return s == null ? 0 : s.length();
}
static int lCharSequence(CharSequence s) {
return s == null ? 0 : s.length();
}
static int iteratorCount_int_close(Iterator i) { try {
int n = 0;
if (i != null) while (i.hasNext()) { i.next(); ++n; }
if (i instanceof AutoCloseable) ((AutoCloseable) i).close();
return n;
} catch (Exception __e) { throw rethrow(__e); } }
static int min(int a, int b) {
return Math.min(a, b);
}
static long min(long a, long b) {
return Math.min(a, b);
}
static float min(float a, float b) { return Math.min(a, b); }
static float min(float a, float b, float c) { return min(min(a, b), c); }
static double min(double a, double b) {
return Math.min(a, b);
}
static double min(double[] c) {
double x = Double.MAX_VALUE;
for (double d : c) x = Math.min(x, d);
return x;
}
static float min(float[] c) {
float x = Float.MAX_VALUE;
for (float d : c) x = Math.min(x, d);
return x;
}
static byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x) x = d;
return x;
}
static short min(short[] c) {
short x = 0x7FFF;
for (short d : c) if (d < x) x = d;
return x;
}
static int min(int[] c) {
int x = Integer.MAX_VALUE;
for (int d : c) if (d < x) x = d;
return x;
}
static boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
// a little kludge for stuff like eq(symbol, "$X")
static boolean eq(Symbol a, String b) {
return eq(str(a), b);
}
static ArrayList emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
// get correct type at once
static ArrayList emptyList(Class c) {
return new ArrayList();
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static String 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 int max(int a, int b) { return Math.max(a, b); }
static int max(int a, int b, int c) { return max(max(a, b), c); }
static long max(int a, long b) { return Math.max((long) a, b); }
static long max(long a, long b) { return Math.max(a, b); }
static double max(int a, double b) { return Math.max((double) a, b); }
static float max(float a, float b) { return Math.max(a, b); }
static double max(double a, double b) { return Math.max(a, b); }
static > A max (Iterable l) {
A max = null;
var it = iterator(l);
if (it.hasNext()) {
max = it.next();
while (it.hasNext()) {
A a = it.next();
if (cmp(a, max) > 0)
max = a;
}
}
return max;
}
/*Nah.
static int max(Collection c) {
int x = Integer.MIN_VALUE;
for (int i : c) x = max(x, i);
ret x;
}*/
static double max(double[] c) {
if (c.length == 0) return Double.MIN_VALUE;
double x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static float max(float[] c) {
if (c.length == 0) return Float.MAX_VALUE;
float x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static byte max(byte[] c) {
byte x = -128;
for (byte d : c) if (d > x) x = d;
return x;
}
static short max(short[] c) {
short x = -0x8000;
for (short d : c) if (d > x) x = d;
return x;
}
static int max(int[] c) {
int x = Integer.MIN_VALUE;
for (int d : c) if (d > x) x = d;
return x;
}
static > A max(A a, A b) {
return cmp(a, b) >= 0 ? a : b;
}
static void _handleError(Error e) {
//call(javax(), '_handleError, e);
}
static Iterator iterator(Iterable c) {
return c == null ? emptyIterator() : c.iterator();
}
static int cmp(Number a, Number b) {
return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue());
}
static int cmp(double a, double b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(int a, int b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(long a, long b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(Object a, Object b) {
if (a == null) return b == null ? 0 : -1;
if (b == null) return 1;
return ((Comparable) a).compareTo(b);
}
static Iterator emptyIterator() {
return Collections.emptyIterator();
}
static class TickerSequence implements IntSize {
TickerSequence() {}
final public TickerSequence setMarket(String market){ return market(market); }
public TickerSequence market(String market) { this.market = market; return this; } final public String getMarket(){ return market(); }
public String market() { return market; }
String market; // e.g. "TRBUSDT"
LongBuffer timestamps = new LongBuffer();
DoubleBuffer prices = new DoubleBuffer();
void add(double price, long timestamp) {
timestamps.add(timestamp);
prices.add(price);
}
void add(double[] prices, long[] timestamps) {
assertEquals(l(prices), l(timestamps));
this.prices.addAll(asList(prices));
this.timestamps.addAll(asList(timestamps));
}
public String toString() {
return "TickerSequence length " + n2(l(prices));
}
TickerSequence subSequence(int start, int end) {
TickerSequence s = new TickerSequence();
s.add(
subDoubleArray(prices.toArray(), start, end),
subArray(timestamps.toArray(), start, end));
return s;
}
TickerSequence cutOffAfterSeconds(double seconds) {
int idx = indexOfTimestamp(startTime()+secondsToMS(seconds));
return subSequence(0, idx);
}
int indexOfTimestamp(double ts) {
return binarySearch_insertionPoint(timestamps.asVirtualList(), lround(ts));
}
long nextTimestamp(double ts) {
return getTimestamp(indexOfTimestamp(ts)+1);
}
double priceAtTimestamp(double ts) {
return getPrice(indexOfTimestamp(ts));
}
public int size() { return l(prices); }
public boolean isEmpty() { return size() == 0; }
TimestampRange timeRange() {
return isEmpty() ? null : new TimestampRange(first(timestamps), last(timestamps));
}
long startTime() { return first(timestamps); }
long endTime() { return last(timestamps); }
double getPrice(int i) { return prices.get(clampToLength(size(), i)); }
long getTimestamp(int i) { return timestamps.get(clampToLength(size(), i)); }
TickerSequence removePlateaus() {
TickerSequence seq = new TickerSequence();
seq.market(market);
int n = size();
for (int i = 0; i < n; i++) {
var value = getPrice(i);
seq.prices.add(value);
seq.timestamps.add(getTimestamp(i));
while (i+1 < n && getPrice(i+1) == value) ++i;
}
return seq;
}
double minPrice() { return doubleMin(prices.toArray()); }
double maxPrice() { return doubleMax(prices.toArray()); }
}
static interface IFieldsToList {
Object[] _fieldsToList();
}
// you still need to implement hasNext() and next()
static abstract class IterableIterator implements Iterator, Iterable {
public Iterator iterator() {
return this;
}
public void remove() {
unsupportedOperation();
}
}
static class DoubleBuffer implements Iterable, IntSize {
double[] data;
int size;
DoubleBuffer() {}
DoubleBuffer(int size) { if (size != 0) data = new double[size]; }
DoubleBuffer(Iterable l) { addAll(l); }
DoubleBuffer(Collection l) { this(l(l)); addAll(l); }
DoubleBuffer(double... data) { this.data = data; size = l(data); }
void add(double i) {
if (size >= lDoubleArray(data)) {
data = resizeDoubleArray(data, Math.max(1, toInt(Math.min(maximumSafeArraySize(), lDoubleArray(data)*2L))));
if (size >= data.length) throw fail("DoubleBuffer too large: " + size);
}
data[size++] = i;
}
void addAll(Iterable l) {
if (l != null) for (double i : l) add(i);
}
double[] toArray() {
return size == 0 ? null : resizeDoubleArray(data, size);
}
double[] toArrayNonNull() {
return unnull(toArray());
}
List toList() {
return doubleArrayToList(data, 0, size);
}
List asVirtualList() {
return new RandomAccessAbstractList() {
public int size() { return size; }
public Double get(int i) { return DoubleBuffer.this.get(i); }
public Double set(int i, Double val) {
Double a = get(i);
data[i] = val;
return a;
}
};
}
void reset() { size = 0; }
void clear() { reset(); }
public int size() { return size; }
boolean isEmpty() { return size == 0; }
double get(int idx) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
return data[idx];
}
void set(int idx, double value) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
data[idx] = value;
}
double popLast() {
if (size == 0) throw fail("empty buffer");
return data[--size];
}
double last() { return data[size-1]; }
double nextToLast() { return data[size-2]; }
public String toString() { return squareBracket(joinWithSpace(toList())); }
public Iterator iterator() {
return new IterableIterator() {
int i = 0;
public boolean hasNext() { return i < size; }
public Double next() {
//if (!hasNext()) fail("Index out of bounds: " + i);
return data[i++];
}
};
}
/*public DoubleIterator doubleIterator() {
ret new DoubleIterator {
int i = 0;
public bool hasNext() { ret i < size; }
public int next() {
//if (!hasNext()) fail("Index out of bounds: " + i);
ret data[i++];
}
toString { ret "Iterator@" + i + " over " + DoubleBuffer.this; }
};
}*/
void trimToSize() {
data = resizeDoubleArray(data, size);
}
int indexOf(double b) {
for (int i = 0; i < size; i++)
if (data[i] == b)
return i;
return -1;
}
double[] subArray(int start, int end) {
return subDoubleArray(data, start, min(end, size));
}
}
static class LongBuffer implements Iterable, ILongQueue {
long[] data;
int size;
LongBuffer() {}
LongBuffer(int size) { if (size != 0) data = new long[size]; }
LongBuffer(Iterable l) {
if (l instanceof Collection) allocate(((Collection) l).size());
addAll(l);
}
public void add(long i) {
if (size >= lLongArray(data)) {
data = resizeLongArray(data, Math.max(1, toInt(Math.min(maximumSafeArraySize(), lLongArray(data)*2L))));
if (size >= data.length) throw fail("LongBuffer too large: " + size);
}
data[size++] = i;
}
void allocate(int n) {
data = resizeLongArray(data, max(n, size()));
}
void addAll(Iterable l) {
if (l != null) for (long i : l) add(i);
}
long[] toArray() {
return size == 0 ? null : resizeLongArray(data, size);
}
List toList() {
return longArrayToList(data, 0, size);
}
List asVirtualList() {
return listFromFunction(__30 -> get(__30), size);
}
void reset() { size = 0; }
void clear() { reset(); }
int size() { return size; }
public boolean isEmpty() { return size == 0; }
long get(int idx) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
return data[idx];
}
void set(int idx, long value) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
data[idx] = value;
}
long popLast() {
if (size == 0) throw fail("empty buffer");
return data[--size];
}
long last() { return data[size-1]; }
long nextToLast() { return data[size-2]; }
public String toString() { return squareBracket(joinWithSpace(toList())); }
public Iterator iterator() {
return new IterableIterator() {
int i = 0;
public boolean hasNext() { return i < size; }
public Long next() {
if (!hasNext()) throw fail("Index out of bounds: " + i);
return data[i++];
}
};
}
void trimToSize() {
data = resizeLongArray(data, size);
}
void remove(int idx) {
arraycopy(data, idx+1, data, idx, size-1-idx);
--size;
}
// don't rely on return value if buffer is empty
public long poll() {
return size == 0 ? -1 : data[--size];
}
}
interface IntSize {
int size();
}
static class TimestampRange implements IFieldsToList{
static final String _fieldOrder = "start end";
Timestamp start;
Timestamp end;
TimestampRange() {}
TimestampRange(Timestamp start, Timestamp end) {
this.end = end;
this.start = start;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + start + ", " + end + ")"; }
public boolean equals(Object o) {
if (!(o instanceof TimestampRange)) return false;
TimestampRange __1 = (TimestampRange) o;
return eq(start, __1.start) && eq(end, __1.end);
}
public int hashCode() {
int h = -2020922905;
h = boostHashCombine(h, _hashCode(start));
h = boostHashCombine(h, _hashCode(end));
return h;
}
public Object[] _fieldsToList() { return new Object[] {start, end}; }
TimestampRange(long start, long end) {
this(new Timestamp(start), new Timestamp(end));
}
final Timestamp startTime(){ return start(); }
Timestamp start() { return start; }
final Timestamp endTime(){ return end(); }
Timestamp end() { return end; }
final TimestampRange startTime(Timestamp start){ return start(start); }
TimestampRange start(Timestamp start) { this.start = start; return this; }
final TimestampRange endTime(Timestamp end){ return end(end); }
TimestampRange end(Timestamp end) { this.end = end; return this; }
boolean complete() { return start != null && end != null; }
Duration duration() { return !complete() ? null : end.minusAsDuration(start); }
}
abstract static class RandomAccessAbstractList extends AbstractList implements RandomAccess {
}
static class Timestamp implements Comparable , IFieldsToList{
long date;
Timestamp(long date) {
this.date = date;}
public boolean equals(Object o) {
if (!(o instanceof Timestamp)) return false;
Timestamp __1 = (Timestamp) o;
return date == __1.date;
}
public int hashCode() {
int h = 2059094262;
h = boostHashCombine(h, _hashCode(date));
return h;
}
public Object[] _fieldsToList() { return new Object[] {date}; }
Timestamp() { date = now(); }
Timestamp(Date date) { if (date != null) this.date = date.getTime(); }
long unixDate() { return date; }
long unixSeconds() { return unixDate()/1000; }
public String toString() { return formatLocalDateWithSeconds(date); }
// Hmm. Should Timestamp(0) be equal to null? Question, questions...
public int compareTo(Timestamp t) {
return t == null ? 1 : cmp(date, t.date);
}
Timestamp plus(Seconds seconds) {
return plus(seconds == null ? null : seconds.getDouble());
}
final Timestamp plusSeconds(double seconds){ return plus(seconds); }
Timestamp plus(double seconds) {
return new Timestamp(date+toMS(seconds));
}
// returns milliseconds
long minus(Timestamp ts) {
return unixDate()-ts.unixDate();
}
long sysTime() {
return clockTimeToSystemTime(date);
}
Duration minusAsDuration(Timestamp ts) {
return Duration.ofMillis(minus(ts));
}
}
static interface ILongQueue {
public boolean isEmpty();
public void add(long element);
// return value is undefined if queue is empty
public long poll();
}
static class Seconds implements Comparable , IFieldsToList{
double seconds;
Seconds() {}
Seconds(double seconds) {
this.seconds = seconds;}
public boolean equals(Object o) {
if (!(o instanceof Seconds)) return false;
Seconds __1 = (Seconds) o;
return seconds == __1.seconds;
}
public int hashCode() {
int h = -660217249;
h = boostHashCombine(h, _hashCode(seconds));
return h;
}
public Object[] _fieldsToList() { return new Object[] {seconds}; }
final double get(){ return seconds(); }
final double getDouble(){ return seconds(); }
double seconds() { return seconds; }
public String toString() { return formatDouble(seconds, 3) + " s"; }
public int compareTo(Seconds s) {
return cmp(seconds, s.seconds);
}
Seconds div(double x) { return new Seconds(get()/x); }
Seconds minus(Seconds x) { return new Seconds(get()-x.get()); }
}
static A assertEquals(Object x, A y) {
return assertEquals("", x, y);
}
static A assertEquals(String msg, Object x, A y) {
if (assertVerbose()) return assertEqualsVerbose(msg, x, y);
if (!(x == null ? y == null : x.equals(y)))
throw fail((msg != null ? msg + ": " : "") + y + " != " + x);
return y;
}
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(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 double[] subDoubleArray(double[] b, int start) { return subDoubleArray(b, start, l(b)); }
static double[] subDoubleArray(double[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start == 0 && end == l(b)) return b;
if (start >= end) return new double[0];
double[] x = new double[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static int[] subArray(int[] b, int start, int end) {
int[] x = new int[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static byte[] subArray(byte[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start >= end) return new byte[0];
byte[] x = new byte[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static long[] subArray(long[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start >= end) return new long[0];
long[] x = new long[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static short[] subArray(short[] b, int start, int end) {
if (start <= 0 && end >= l(b)) return b;
short[] x = new short[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static float[] subArray(float[] b, int start, int end) {
float[] x = new float[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static Object[] subArray(Object[] b, int start) {
return subArray(b, start, l(b));
}
static Object[] subArray(Object[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start >= end) return new Object[0];
Object[] x = new Object[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static long secondsToMS(double seconds) {
return toMS(seconds);
}
static > int binarySearch_insertionPoint(List l, A a) {
int i = Collections.binarySearch(l, a);
return i < 0 ? -i-1 : i;
}
static long lround(double d) {
return Math.round(d);
}
static long lround(Number n) {
return lround(toDouble(n));
}
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(byte[] a) { return a == null || a.length == 0; }
static boolean isEmpty(Map map) {
return map == null || map.isEmpty();
}
static boolean isEmpty(AppendableChain c) { return c == null; }
static boolean isEmpty(IntSize l) { return l == null || l.size() == 0; }
static Object first(Object list) {
return first((Iterable) list);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static Pair first(Map map) {
return mapEntryToPair(first(entrySet(map)));
}
static Pair first(MultiMap mm) {
if (mm == null) return null;
var e = first(mm.data.entrySet());
if (e == null) return null;
return pair(e.getKey(), first(e.getValue()));
}
static A first(IterableIterator i) {
return first((Iterator) i);
}
static A first(Iterator i) {
return i == null || !i.hasNext() ? null : i.next();
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static Byte first(byte[] l) {
return empty(l) ? null : l[0];
}
static A first(A[] l, IF1 pred) {
return firstThat(l, pred);
}
static A first(Iterable l, IF1 pred) {
return firstThat(l, pred);
}
static A first(IF1 pred, Iterable l) {
return firstThat(pred, l);
}
static A first(AppendableChain a) {
return a == null ? null : a.element;
}
static A last(List l) {
return empty(l) ? null : l.get(l.size()-1);
}
static char last(String s) {
return empty(s) ? '#' : s.charAt(l(s)-1);
}
static byte last(byte[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static int last(int[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static long last(long[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static double last(double[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static A last(A[] a) {
return l(a) != 0 ? a[l(a)-1] : null;
}
static A last(Iterator it) {
A a = null;
while (it.hasNext()) { ping(); a = it.next(); }
return a;
}
static A last(Collection l) {
if (l == null) return null;
if (l instanceof List) return (A) last((List) l);
if (l instanceof SortedSet) return (A) last((SortedSet) l);
Iterator it = iterator(l);
A a = null;
while (it.hasNext()) { ping(); a = it.next(); }
return a;
}
static A last(SortedSet l) {
return l == null ? null : l.last();
}
static A last(ReverseChain l) {
return l == null ? null : l.element;
}
static double last(DoubleBuffer l) {
return l.last();
}
static long last(LongBuffer l) {
return l.last();
}
static A last(CompactLinkedHashSet set) {
return set == null ? null : set.last();
}
static int clampToLength(int length, int i) {
return clamp(i, 0, length-1);
}
static double doubleMin(Iterable l) {
double min = Double.MAX_VALUE;
for (double d : unnullForIteration(l))
min = Math.min(min, d);
return min;
}
static double doubleMin(double... l) {
double min = Double.MAX_VALUE;
for (double d : unnullForIteration(l))
min = Math.min(min, d);
return min;
}
static double doubleMax(Iterable l) {
double max = -Double.MAX_VALUE;
for (double d : unnullForIteration(l))
max = Math.max(max, d);
return max;
}
static double doubleMax(double[] l) {
double max = -Double.MAX_VALUE;
for (double d : unnullForIteration(l))
max = Math.max(max, d);
return max;
}
static double doubleMax(double[] l, int from, int to) {
double max = -Double.MAX_VALUE;
for (int i = from; i < to; i++)
max = Math.max(max, l[i]);
return max;
}
static UnsupportedOperationException unsupportedOperation() {
throw new UnsupportedOperationException();
}
static void addAll(Collection c, Iterable b) {
if (c != null && b != null) for (A a : b) c.add(a);
}
static boolean addAll(Collection c, Collection b) {
return c != null && b != null && c.addAll(b);
}
static boolean addAll(Collection c, B... b) {
return c != null && b != null && c.addAll(Arrays.asList(b));
}
static Map addAll(Map a, Map extends A,? extends B> b) {
if (a != null && b != null) a.putAll(b);
return a;
}
static A addAll(A c, Collection extends Component> components) {
return addComponents(c, components);
}
static A addAll(A c, Component... components) {
return addComponents(c, components);
}
static int lDoubleArray(double[] a) {
return a == null ? 0 : a.length;
}
static double[] resizeDoubleArray(double[] a, int n) {
if (n == l(a)) return a;
double[] b = new double[n];
arraycopy(a, 0, b, 0, min(l(a), n));
return b;
}
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);
if (o instanceof Boolean)
return boolToInt((Boolean) 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 int maximumSafeArraySize() {
return Integer.MAX_VALUE-8;
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(Object... objects) { throw new Fail(objects); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static void add(BitSet bs, int i) {
bs.set(i);
}
static boolean add(Collection c, A a) {
return c != null && c.add(a);
}
static void add(Container c, Component x) {
addToContainer(c, x);
}
static long add(AtomicLong l, long b) {
return l.addAndGet(b);
}
static String unnull(String s) {
return s == null ? "" : s;
}
static Collection unnull(Collection l) {
return l == null ? emptyList() : l;
}
static List unnull(List l) { return l == null ? emptyList() : l; }
static int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; }
static float[] unnull(float[] l) { return l == null ? emptyFloatArray() : l; }
static Map unnull(Map l) {
return l == null ? emptyMap() : l;
}
static Iterable unnull(Iterable i) {
return i == null ? emptyList() : i;
}
static A[] unnull(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnull(BitSet b) {
return b == null ? new BitSet() : b;
}
static Pt unnull(Pt p) {
return p == null ? new Pt() : p;
}
//ifclass Symbol
static Symbol unnull(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnull(Pair p) {
return p != null ? p : new Pair(null, null);
}
static int unnull(Integer i) { return i == null ? 0 : i; }
static long unnull(Long l) { return l == null ? 0L : l; }
static double unnull(Double l) { return l == null ? 0.0 : l; }
static Object[] toArray(Collection c) {
return toObjectArray(c);
}
static A[] toArray(Class type, Iterable c) {
return toArray(c, type);
}
static A[] toArray(Class type, Collection c) {
return toArray(c, type);
}
static A[] toArray(Collection c, Class type) {
A[] a = arrayOfType(l(c), type);
if (a.length == 0) return a;
asList(c).toArray(a);
return a;
}
static A[] toArray(Iterable c, Class type) {
var c2 = asList(c);
A[] a = arrayOfType(l(c2), type);
if (a.length == 0) return a;
c2.toArray(a);
return a;
}
// array must have correct length and will be filled
static A[] toArray(A[] array, Collection c) {
if (array == null || c == null) return null;
asList(c).toArray(array);
return array;
}
static ArrayList doubleArrayToList(double[] a) {
if (a == null) return null;
return doubleArrayToList(a, 0, a.length);
}
// no range checking on from/to in the interest of speed
static ArrayList doubleArrayToList(double[] a, int from, int to) {
if (a == null) return null;
ArrayList < Double > l = new ArrayList<>(to-from);
for (int i = from; i < to; i++) l.add(a[i]);
return l;
}
static List asVirtualList(A[] a) {
return wrapArrayAsList(a);
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static A get(List l, int idx) {
return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static B get(Map map, A key) {
ret map != null ? map.get(key) : null;
}*/
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
if (o == null) return null;
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
Field f = getOpt_findField(o.getClass(), field);
if (f != null) {
makeAccessible(f);
return f.get(o);
}
if (o instanceof DynamicObject)
return getOptDynOnly(((DynamicObject) o), field);
} catch (Exception e) {
throw asRuntimeException(e);
}
throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(String field, Object o) {
return get_raw(o, field);
}
static Object get_raw(Object o, String field) { try {
if (o == null) return null;
Field f = get_findField(o.getClass(), field);
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
makeAccessible(f);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static Object get(String field, Object o) {
return get(o, field);
}
static boolean get(BitSet bs, int idx) {
return bs != null && bs.get(idx);
}
static A set(A o, String field, Object value) {
if (o == null) return null;
if (o instanceof Class) set((Class) o, field, value);
else try {
Field f = set_findField(o.getClass(), field);
makeAccessible(f);
smartSet(f, o, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
return o;
}
static void set(Class c, String field, Object value) {
if (c == null) return;
try {
Field f = set_findStaticField(c, field);
makeAccessible(f);
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() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field 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 void set(BitSet bs, int idx) {
{ if (bs != null) bs.set(idx); }
}
static String squareBracket(String s) {
return "[" + s + "]";
}
static String joinWithSpace(Iterable c) {
return join(" ", c);
}
static String joinWithSpace(Object... c) {
return join(" ", c);
}
static int lLongArray(long[] a) {
return a == null ? 0 : a.length;
}
static long[] resizeLongArray(long[] a, int n) {
if (n == lLongArray(a)) return a;
long[] b = new long[n];
arraycopy(a, 0, b, 0, Math.min(lLongArray(a), n));
return b;
}
static ArrayList longArrayToList(long[] a) {
if (a == null) return null;
return longArrayToList(a, 0, a.length);
}
// no range checking on from/to in the interest of S P E E E E E EEED
static ArrayList longArrayToList(long[] a, int from, int to) {
if (a == null) return null;
ArrayList < Long > l = new ArrayList<>(to-from);
for (int i = from; i < to; i++) l.add(a[i]);
return l;
}
static class ListFromFunction extends RandomAccessAbstractList implements IFieldsToList{
int n;
IF1 f;
ListFromFunction() {}
ListFromFunction(int n, IF1 f) {
this.f = f;
this.n = n;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + n + ", " + f + ")"; }public Object[] _fieldsToList() { return new Object[] {n, f}; }
public int size() { return n; }
public A get(int i) { return f.get(i); }
}
static List listFromFunction(int n, IF1 f) {
return new ListFromFunction(n, f);
}
static List listFromFunction(IF1 f, int n) {
return new ListFromFunction(n, f);
}
static void arraycopy(Object[] a, Object[] b) {
if (a != null && b != null)
arraycopy(a, 0, b, 0, Math.min(a.length, b.length));
}
static void arraycopy(Object src, int srcPos, int destPos, int n) { arraycopy(src, srcPos, src, destPos, n); }
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) {
if (n != 0)
System.arraycopy(src, srcPos, dest, destPos, n);
}
static int boostHashCombine(int a, int b) {
return a ^ (b + 0x9e3779b9 + (a << 6) + (a >>> 2));
// OLD (changed) 2022/3/10: ret a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2));
}
static int _hashCode(Object a) {
return a == null ? 0 : a.hashCode();
}
static long now_virtualTime;
static long now() {
return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis();
}
static String formatLocalDateWithSeconds(long time) {
return localDateWithSeconds(time);
}
static String formatLocalDateWithSeconds() {
return localDateWithSeconds();
}
static BigInteger plus(BigInteger a, BigInteger b) {
return a.add(b);
}
static BigInteger plus(BigInteger a, long b) {
return a.add(bigint(b));
}
static long plus(long a, long b) { return a+b; }
static int plus(int a, int b) { return a+b; }
static float plus(float a, float b) { return a+b; }
static double plus(double a, double b) { return a+b; }
static long toMS(double seconds) {
return (long) (seconds*1000);
}
static long clockTimeToSystemTime(long now) {
return now == 0 ? 0 : now + clockToSysTimeDiff();
}
static List minus(Collection a, Object... b) {
Set set = asSet(b);
List l = new ArrayList();
for (Object s : unnull(a))
if (!set.contains(s))
l.add(s);
return l;
}
static BigInteger minus(BigInteger a, BigInteger b) {
return a.subtract(b);
}
static Complex minus(Complex c) {
return c == null ? null : complex(-c.re(), -c.im());
}
static int minus(int a, int b) {
return a-b;
}
static double minus(double a, double b) {
return a-b;
}
static long minus(long a, long b) {
return a-b;
}
static int seconds() {
return seconds(java.util.Calendar.getInstance());
}
static int seconds(java.util.Calendar c) {
return c.get(java.util.Calendar.SECOND);
}
static String formatDouble(double d, int digits) {
String format = digits <= 0 ? "0" : "0." + rep(digits, '#');
return decimalFormatEnglish(format, d);
}
static String formatDouble(double d) {
return str(d);
}
static ThreadLocal assertVerbose_value = new ThreadLocal();
static void assertVerbose(boolean b) {
assertVerbose_value.set(b);
}
static boolean assertVerbose() { return isTrue(assertVerbose_value.get()); }
static A assertEqualsVerbose(Object x, A y) {
assertEqualsVerbose((String) null, x, y);
return y;
}
// x = expected, y = actual
static A assertEqualsVerbose(String msg, Object x, A y) {
if (!eq(x, y)) {
throw fail((nempty(msg) ? msg + ": " : "") + "expected: "+ x + ", got: " + y);
} else
print("OK" + (empty(msg) ? "" : " " + msg) + ": " + /*sfu*/(x));
return y;
}
static String nullIfEmpty(String s) {
return isEmpty(s) ? null : s;
}
static Map nullIfEmpty(Map map) {
return isEmpty(map) ? null : map;
}
static List nullIfEmpty(List l) {
return isEmpty(l) ? null : l;
}
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(IMultiMap mm) { return mm == null || mm.size() == 0; }
static boolean empty(File f) { return getFileSize(f) == 0; }
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 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 double toDouble(Object o) {
if (o instanceof Number)
return ((Number) o).doubleValue();
if (o instanceof BigInteger)
return ((BigInteger) o).doubleValue();
if (o instanceof String)
return parseDouble((String) o);
if (o == null) return 0.0;
throw fail(o);
}
static Pair mapEntryToPair(Map.Entry e) {
return e == null ? null : pair(e.getKey(), e.getValue());
}
static Set> entrySet(Map map) {
return _entrySet(map);
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static A firstThat(Iterable l, IF1 pred) {
for (A a : unnullForIteration(l))
if (pred.get(a))
return a;
return null;
}
static A firstThat(A[] l, IF1 pred) {
for (A a : unnullForIteration(l))
if (pred.get(a))
return a;
return null;
}
static A firstThat(IF1 pred, Iterable l) {
return firstThat(l, pred);
}
static A firstThat(IF1 pred, A[] l) {
return firstThat(l, pred);
}
// 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 float clamp(float x, float a, float b) {
return x < a ? a : x > b ? b : x;
}
static double clamp(double x, double a, double b) {
return x < a ? a : x > b ? b : x;
}
static int clamp(int x, int a, int b) {
return x < a ? a : x > b ? b : x;
}
static long clamp(long x, long a, long b) {
return x < a ? a : x > b ? b : x;
}
static String unnullForIteration(String s) {
return s == null ? "" : s;
}
static Collection unnullForIteration(Collection l) {
return l == null ? immutableEmptyList() : l;
}
static List unnullForIteration(List l) { return l == null ? immutableEmptyList() : l; }
static byte[] unnullForIteration(byte[] l) { return l == null ? emptyByteArray() : l; }
static int[] unnullForIteration(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnullForIteration(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnullForIteration(double[] l) { return l == null ? emptyDoubleArray() : l; }
static short[] unnullForIteration(short[] l) { return l == null ? emptyShortArray() : l; }
static Map unnullForIteration(Map l) {
return l == null ? immutableEmptyMap() : l;
}
static Iterable unnullForIteration(Iterable i) {
return i == null ? immutableEmptyList() : i;
}
static A[] unnullForIteration(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnullForIteration(BitSet b) {
return b == null ? new BitSet() : b;
}
static Pt unnullForIteration(Pt p) {
return p == null ? new Pt() : p;
}
//ifclass Symbol
static Symbol unnullForIteration(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnullForIteration(Pair p) {
return p != null ? p : new Pair(null, null);
}
static long unnullForIteration(Long l) { return l == null ? 0L : l; }
static A addComponents(A c, Collection extends Component> components) {
if (nempty(components)) { swing(() -> {
for (Component comp : components)
if (comp != null)
c.add(comp);
revalidate(c);
}); }
return c;
}
static A addComponents(A c, Component... components) {
return addComponents(c, asList(components));
}
static int parseInt(String s) {
return emptyString(s) ? 0 : Integer.parseInt(s);
}
static int parseInt(char c) {
return Integer.parseInt(str(c));
}
static int boolToInt(boolean b) {
return b ? 1 : 0;
}
static String getClassName(Object o) {
return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
}
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static void addToContainer(Container a, Component... b) {
if (a == null) return;
{ swing(() -> {
for (Component c : unnullForIteration(b))
if (c != null)
a.add(c);
}); }
}
static int[] emptyIntArray_a = new int[0];
static int[] emptyIntArray() { return emptyIntArray_a; }
static char[] emptyCharArray = new char[0];
static char[] emptyCharArray() { return emptyCharArray; }
static double[] emptyDoubleArray = new double[0];
static double[] emptyDoubleArray() { return emptyDoubleArray; }
static float[] emptyFloatArray = new float[0];
static float[] emptyFloatArray() { return emptyFloatArray; }
static Map emptyMap() {
return new HashMap();
}
static Object[] emptyObjectArray_a = new Object[0];
static Object[] emptyObjectArray() { return emptyObjectArray_a; }
static Symbol emptySymbol_value;
static Symbol emptySymbol() {
if (emptySymbol_value == null) emptySymbol_value = symbol("");
return emptySymbol_value;
}
// binary legacy signature
static Object[] toObjectArray(Collection c) {
return toObjectArray((Iterable) c);
}
static Object[] toObjectArray(Iterable c) {
List l = asList(c);
return l.toArray(new Object[l.size()]);
}
static A[] arrayOfType(Class type, int n) {
return makeArray(type, n);
}
static A[] arrayOfType(int n, Class type) {
return arrayOfType(type, n);
}
static List wrapArrayAsList(A[] a) {
return a == null ? null : Arrays.asList(a);
}
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 Field makeAccessible(Field f) {
try {
f.setAccessible(true);
} catch (Throwable e) {
// Note: The error reporting only works with Java VM option --illegal-access=deny
vmBus_send("makeAccessible_error", e, f);
}
return f;
}
static Method makeAccessible(Method m) {
try {
m.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, m);
}
return m;
}
static Constructor makeAccessible(Constructor c) {
try {
c.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, c);
}
return c;
}
static Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
static void smartSet(Field f, Object o, Object value) throws Exception {
try {
f.set(o, value);
} catch (Exception e) {
Class type = f.getType();
// take care of common case (long to int)
if (type == int.class && value instanceof Long)
{ f.set(o, ((Long) value).intValue()); return; }
if (type == boolean.class && value instanceof String)
{ f.set(o, isTrueOrYes(((String) value))); return; }
if (type == LinkedHashMap.class && value instanceof Map)
{ f.set(o, asLinkedHashMap((Map) value)); return; }
throw e;
}
}
public static String join(String glue, Iterable strings) {
if (strings == null) return "";
if (strings instanceof Collection) {
if (((Collection) strings).size() == 1) return str(first((Collection) 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(String glue, Object... strings) {
return join(glue, Arrays.asList(strings));
}
static String join(Iterable strings) {
return join("", strings);
}
static String join(Iterable strings, String glue) {
return join(glue, strings);
}
public static String join(String[] strings) {
return join("", strings);
}
static String join(String glue, Pair p) {
return p == null ? "" : str(p.a) + glue + str(p.b);
}
static String localDateWithSeconds(long time) {
SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm:ss");
return format.format(time);
}
static String localDateWithSeconds() {
return localDateWithSeconds(now());
}
static BigInteger bigint(String s) {
return new BigInteger(s);
}
static BigInteger bigint(long l) {
return BigInteger.valueOf(l);
}
static long clockToSysTimeDiff() {
return sysNow()-now();
}
static Set asSet(Object[] array) {
HashSet set = new HashSet();
for (Object o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(String[] array) {
TreeSet set = new TreeSet();
for (String o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(Iterable l) {
if (l instanceof Set) return (Set) l;
HashSet set = new HashSet();
for (A o : unnull(l))
if (o != null)
set.add(o);
return set;
}
static Complex complex(double re, double im) {
return new Complex(re, im);
}
static Complex complex(double re) {
return new Complex(re, 0.0);
}
static Complex complex(double[] reIm) {
if (empty(reIm)) return null;
if (l(reIm) != 2) throw fail("Need 2 doubles to make complex number");
return complex(reIm[0], reIm[1]);
}
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 List rep(int n, A a) {
return repeat(n, a);
}
static String decimalFormatEnglish(String format, double d) {
return decimalFormatEnglish(format).format(d);
}
static java.text.DecimalFormat decimalFormatEnglish(String format) {
return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH));
}
static boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
if (o instanceof ThreadLocal) // TODO: remove this
return isTrue(((ThreadLocal) o).get());
throw fail(getClassName(o));
}
static boolean isTrue(Boolean b) {
return b != null && b.booleanValue();
}
static boolean nempty(Collection c) {
return !empty(c);
}
static boolean nempty(CharSequence s) {
return !empty(s);
}
static boolean nempty(Object[] o) { return !empty(o); }
static boolean nempty(byte[] o) { return !empty(o); }
static boolean nempty(int[] o) { return !empty(o); }
static boolean nempty(BitSet bs) { return !empty(bs); }
static boolean nempty(Map m) {
return !empty(m);
}
static boolean nempty(Iterator i) {
return i != null && i.hasNext();
}
static boolean nempty(IMultiMap mm) { return mm != null && mm.size() != 0; }
static boolean nempty(Object o) { return !empty(o); }
static boolean nempty(LongBuffer b) { return b != null && !b.isEmpty(); }
static boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; }
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