Warning : session_start(): open(/var/lib/php/sessions/sess_5f3pga68kulqkk3l17c965sbtt, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning : session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import 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.awt.geom.Line2D;
import java.awt.geom.*;
import static x30_pkg.x30_util.DynamicObject;
import java.nio.file.Path;
import java.text.*;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
class main {
abstract static class AbstractTickerPainter extends ScaledDiagram implements G2Drawable, MakesBufferedImage {
final public AbstractTickerPainter setTicker(TickerSequence ticker){ return ticker(ticker); }
public AbstractTickerPainter ticker(TickerSequence ticker) { this.ticker = ticker; return this; } final public TickerSequence getTicker(){ return ticker(); }
public TickerSequence ticker() { return ticker; }
TickerSequence ticker;
// the following two are old, use priceCells instead
final public AbstractTickerPainter setPercentLineDistance(double percentLineDistance){ return percentLineDistance(percentLineDistance); }
public AbstractTickerPainter percentLineDistance(double percentLineDistance) { this.percentLineDistance = percentLineDistance; return this; } final public double getPercentLineDistance(){ return percentLineDistance(); }
public double percentLineDistance() { return percentLineDistance; }
double percentLineDistance;
final public AbstractTickerPainter setDrawPercentLines(boolean drawPercentLines){ return drawPercentLines(drawPercentLines); }
public AbstractTickerPainter drawPercentLines(boolean drawPercentLines) { this.drawPercentLines = drawPercentLines; return this; } final public boolean getDrawPercentLines(){ return drawPercentLines(); }
public boolean drawPercentLines() { return drawPercentLines; }
boolean drawPercentLines = false;
final public AbstractTickerPainter setPriceCells(PriceCells priceCells){ return priceCells(priceCells); }
public AbstractTickerPainter priceCells(PriceCells priceCells) { this.priceCells = priceCells; return this; } final public PriceCells getPriceCells(){ return priceCells(); }
public PriceCells priceCells() { return priceCells; }
PriceCells priceCells;
final public AbstractTickerPainter setPercentStripesColor(Color percentStripesColor){ return percentStripesColor(percentStripesColor); }
public AbstractTickerPainter percentStripesColor(Color percentStripesColor) { this.percentStripesColor = percentStripesColor; return this; } final public Color getPercentStripesColor(){ return percentStripesColor(); }
public Color percentStripesColor() { return percentStripesColor; }
Color percentStripesColor = Color.darkGray;
List positions = new ArrayList();
List additionalObjects = new ArrayList();
final public BufferedImage getBufferedImage(){ return render(); }
public BufferedImage render() {
// Make black image
var img = blackImage(w, h);
var g = img.createGraphics();
drawOn(g);
return img;
}
void drawPercentLines(Graphics2D g) {
if (priceCells != null) {
int cellNumber = ifloor(priceCells.toCellNumber(verticalRange.end));
int safety = 250;
while (safety-- > 0) {
double y2 = priceCells.fromCellNumber(cellNumber-1);
if (y2 < verticalRange.start) break;
double y = priceCells.fromCellNumber(cellNumber);
var yy = iround(yToScreen(y));
var yy2 = iround(yToScreen(y2));
//drawLine(g, 0, yy, w-1, yy, Color.gray);
fillRect(g, 0, yy, w-1, yy2-yy, percentStripesColor);
cellNumber -= 2;
}
}
}
void drawPositions(Graphics2D g) {
for (var position : positions) {
var time = position.openingTime();
var price = position.openingPrice();
var x = xToScreen(time);
var y = yToScreen(price);
var color = colorForPosition(position);
// Mark opening point
fillRect(g, rectAroundPt(iround(x), iround(y), 10), color);
if (not(position.isOpen())) {
time = position.closingTime();
price = position.closingPrice();
var x2 = xToScreen(time);
var y2 = yToScreen(price);
drawArrowBetweenPoints(g, toPt_round(doublePt(x, y)), toPt_round(doublePt(x2, y2)), color);
}
}
}
void drawAdditionalObjects(Graphics2D g) {
for (var o : additionalObjects) { try {
o.drawOn(g);
} catch (Throwable __e) { pcallFail(__e); }}
}
void addVerticalLine(double x) { addVerticalLine(x, Color.gray); }
void addVerticalLine(double x, Color color) {
additionalObjects.add(g -> drawVerticalLine(g, x, color));
}
void add(G2Drawable object) {
addIfNotNull(additionalObjects, object);
}
void drawVerticalLine(Graphics2D g, double x) { drawVerticalLine(g, x, Color.gray); }
void drawVerticalLine(Graphics2D g, double x, Color color) {
int xScreen = iround(xToScreen(x));
drawLine(g, xScreen, 0, xScreen, h-1, color);
}
void addHorizontalLine(double y) { addHorizontalLine(y, Color.gray); }
void addHorizontalLine(double y, Color color) {
additionalObjects.add(g -> drawHorizontalLine(g, y, color));
}
void drawHorizontalLine(Graphics2D g, double y) { drawHorizontalLine(g, y, Color.gray); }
void drawHorizontalLine(Graphics2D g, double y, Color color) {
int yScreen = iround(yToScreen(y));
drawLine(g, 0, yScreen, w-1, yScreen, color);
}
DoubleRange horizontalRangeForTicker(TickerSequence ticker) {
var timeRange = ticker.timeRange();
if (timeRange == null) return null;
return doubleRange(timeRange.startTime().unixDate(), timeRange.endTime().unixDate());
}
DoubleRange verticalRangeForTicker(TickerSequence ticker) {
return doubleRange(ticker.minPrice(), ticker.maxPrice());
}
void addTimeGrid(double minutes) {
additionalObjects.add(g -> drawTimeGrid(g, minutes));
}
void drawTimeGrid(Graphics2D g, double minutes) {
double ms = minutesToMS(minutes);
assertTrue(ms >= 100);
double time = roundUpTo(ms, horizontalRange().start);
while (time < horizontalRange().end) {
drawVerticalLine(g, time);
time += ms;
}
}
class LineIndicator implements G2Drawable {
final public LineIndicator setValues(TickerSequence values){ return values(values); }
public LineIndicator values(TickerSequence values) { this.values = values; return this; } final public TickerSequence getValues(){ return values(); }
public TickerSequence values() { return values; }
TickerSequence values;
final public LineIndicator setColor(Color color){ return color(color); }
public LineIndicator color(Color color) { this.color = color; return this; } final public Color getColor(){ return color(); }
public Color color() { return color; }
Color color = Color.yellow;
LineIndicator() {}
LineIndicator(TickerSequence values) {
this.values = values;}
LineIndicator(TickerSequence values, Color color) {
this.color = color;
this.values = values;}
public void drawOn(Graphics2D g) {
g.setColor(color);
var xRange = roundToIntRange(xRange());
var sub = values.subSequenceByTimestamps(
lround(xFromScreen(xRange.start)),
lround(xFromScreen(xRange.end)));
int lastx = 0, lasty = 0;
for (int i = 0; i < sub.size(); i++) {
double price = sub.getPrice(i);
long time = sub.getTimestamp(i);
int x = iround(xToScreen(time));
int y = iround(yToScreen(price));
if (i != 0)
g.drawLine(lastx, lasty, x, y);
lastx = x;
lasty = y;
}
}
}
final AbstractTickerPainter cellSize(double cellSize){ return priceCells(cellSize); }
AbstractTickerPainter priceCells(double cellSize) {
return priceCells(new GeometricPriceCells(cellSize));
}
transient IF1 colorForPosition;
Color colorForPosition(TradingPosition position) { return colorForPosition != null ? colorForPosition.get(position) : colorForPosition_base(position); }
final Color colorForPosition_fallback(IF1 _f, TradingPosition position) { return _f != null ? _f.get(position) : colorForPosition_base(position); }
Color colorForPosition_base(TradingPosition position) {
boolean winner = position.isWinner();
//bool green = position.isLong();
//var color = colorFromHex(green ? "1da2b4" : "f1493f");
return winner
? directionToCandleColor(position.direction())
: position.isLong() ? Color.yellow : Color.blue;
}
}
static BufferedImage render(WidthAndHeight size, G2Drawable drawable) {
return drawableToImage(size, drawable);
}
static BufferedImage blackImage(int w, int h) {
return newBufferedImage(w, h, Color.black);
}
static BufferedImage blackImage(int size) {
return blackImage(size, size);
}
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 int iround(double d) {
return (int) Math.round(d);
}
static int iround(Number n) {
return iround(toDouble(n));
}
static void fillRect(BufferedImage image, int x, int y, int w, int h, Color color) {
Graphics2D g = imageGraphics(image);
fillRect(g, x, y, w, h, color);
g.dispose();
}
static void fillRect(Graphics g, Color color, int x, int y, int w, int h) {
fillRect(g, x, y, w, h, color);
}
static void fillRect(Graphics/*2D*/ g, int x, int y, int w, int h, Color color) {
g.setColor(color);
g.fillRect(x, y, w, h);
}
// draw on currentImage()
static void fillRect(int x, int y, int w, int h, Color color) {
fillRect(currentImage(), x, y, w, h, color);
}
static void fillRect(Rect r, Color color) {
fillRect(r.x, r.y, r.w, r.h, color);
}
static void fillRect(BufferedImage image, Rect r, Color c) {
if (r != null) fillRect(image, r.x, r.y, r.w, r.h, c);
}
static void fillRect(Graphics/*2D*/ g, Rect r, Color c) {
if (r != null) fillRect(g, r.x, r.y, r.w, r.h, c);
}
static Rect rectAroundPt(Pt p, int w) { return rectAroundPt(p, w, w); }
static Rect rectAroundPt(Pt p, int w, int h) {
return rectAround(p, w, h);
}
static Rect rectAroundPt(int x, int y, int w) { return rectAroundPt(x, y, w, w); }
static Rect rectAroundPt(int x, int y, int w, int h) {
return rectAround(x, y, w, h);
}
static Boolean not(Boolean b) {
return b == null ? null : !b;
}
static int drawArrowBetweenPoints_width = 4;
static double drawArrowBetweenPoints_headScale = 2;
static void drawArrowBetweenPoints(Graphics2D g, Pt p1, Pt p2, Color color) {
int x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y;
double dist = pointDistance(x1, y1, x2, y2);
double headSize = drawArrowBetweenPoints_width*drawArrowBetweenPoints_headScale*drawArrowHead_length+2; // 2 = gap
DoublePt v = blendDoublePts(new DoublePt(x2, y2), new DoublePt(x1, y1), headSize/dist);
DoublePt p = blendDoublePts(new DoublePt(x2, y2), new DoublePt(x1, y1), 0);
g.setColor(color);
g.setStroke(new BasicStroke(drawArrowBetweenPoints_width));
g.draw(new Line2D.Double(x1, y1, v.x, v.y));
drawArrowHead(g, x1, y1, p.x, p.y, drawArrowBetweenPoints_width*drawArrowBetweenPoints_headScale);
}
static Pt toPt_round(IDoublePt pt) {
return pt(iround(pt.x_double()), iround(pt.y_double()));
}
static DoublePt doublePt(double x) { return doublePt(x, x); }
static DoublePt doublePt(double x, double y) {
return new DoublePt(x, y);
}
static void pcallFail(Throwable e) {
pcallPolicyForThread().handlePcallFail(e);
}
static void pcallFail(String msg) {
pcallFail(new Throwable(msg));
}
static boolean addIfNotNull(Collection l, A a) {
return a != null && l != null & l.add(a);
}
static void addIfNotNull(MultiSet ms, A a) {
if (a != null && ms != null) ms.add(a);
}
static void drawLine(BufferedImage image, int x1, int y1, int x2, int y2, Color color) {
drawLine(imageGraphics(image), x1, y1, x2, y2, color);
}
static void drawLine(Graphics2D g, int x1, int y1, int x2, int y2, Color color) {
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
}
static void drawLine(BufferedImage image, Pt a, Pt b, Color color) {
drawLine(imageGraphics(image), a, b, color);
}
static void drawLine(Graphics2D g, Pt a, Pt b, Color color) {
drawLine(g, a.x, a.y, b.x, b.y, color);
}
static DoubleRange doubleRange(double start, double end) {
return new DoubleRange(start, end);
}
static long minutesToMS(double minutes) {
return round(minutes*60*1000);
}
static void assertTrue(Object o) {
if (!(eq(o, true) /*|| isTrue(pcallF(o))*/))
throw fail(str(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 assertTrue(Scorer scorer, boolean b) {
scorer.add(b);
return b;
}
static int roundUpTo(int n, int x) {
return (x+n-1)/n*n;
}
static long roundUpTo(long n, long x) {
return (x+n-1)/n*n;
}
static double roundUpTo(double n, double x) {
return floor((x+n-1)/n)*n;
}
static Collection values(Map map) {
return map == null ? emptyList() : map.values();
}
// convenience shortcut for values_gen
static Collection values(Object map) {
return values((Map) map);
}
static Collection values(MultiMap mm) {
return mm == null ? emptyList() : concatLists(values(mm.data));
}
static java.awt.Color color(String hex) {
return awtColor(hex);
}
static Color getColor(BufferedImage img, int x, int y) {
return colorFromRGBA(img.getRGB(x, y));
}
static Color getColor(BufferedImage img, Pt p) {
return colorFromRGBA(img.getRGB(p.x, p.y));
}
static IntRange roundToIntRange(DoubleRange r) {
return r == null ? null : new IntRange(iround(r.start), iround(r.end));
}
static long lround(double d) {
return Math.round(d);
}
static long lround(Number n) {
return lround(toDouble(n));
}
static Color directionToCandleColor(double direction) {
return direction < 0 ? colorFromHex("f1493f")
: direction > 0 ? colorFromHex("1da2b4")
: Color.white;
}
static BufferedImage drawableToImage(WidthAndHeight size, G2Drawable drawable) {
var img = whiteImage(size);
{ if (drawable != null) drawable.drawOn(img); }
return img;
}
// undefined color, seems to be all black in practice
// This is without alpha?
static BufferedImage newBufferedImage(int w, int h) {
return new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
}
static BufferedImage newBufferedImage(int w, int h, Color color) {
BufferedImage img = newBufferedImage(w, h);
Graphics2D g = img.createGraphics();
g.setColor(or(color, Color.white));
g.fillRect(0, 0, w, h);
return img;
}
static BufferedImage newBufferedImage(Pt p, Color color) {
return newBufferedImage(p.x, p.y, color);
}
static BufferedImage newBufferedImage(WidthAndHeight size, Color color) {
return newBufferedImage(size.w(), size.h(), color);
}
// This one is with alpha...
static BufferedImage newBufferedImage(int w, int h, int[] pixels) {
return intArrayToBufferedImage(pixels, w, h);
}
static IntRange intRange(int start, int end) {
return new IntRange(start, end);
}
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 ThreadLocal imageGraphics_antiAlias = new ThreadLocal();
static Graphics2D imageGraphics(BufferedImage img) {
return !isFalse(imageGraphics_antiAlias.get()) ? antiAliasGraphics(img) : createGraphics(img);
}
static ThreadLocal currentImage_var = new ThreadLocal();
static BufferedImage currentImage() {
return currentImage_var.get();
}
static void currentImage(BufferedImage img) {
currentImage_var.set(img);
}
static Rect rectAround(Pt p, int w) { return rectAround(p, w, w); }
static Rect rectAround(Pt p, int w, int h) {
return new Rect(p.x-w/2, p.y-h/2, w, h);
}
static Rect rectAround(int x, int y, int w, int h) {
return new Rect(x-w/2, y-h/2, w, h);
}
static double pointDistance(Pt a, Pt b) {
return sqrt(sqr(a.x-b.x) + sqr(a.y-b.y));
}
static double pointDistance(double x1, double y1, double x2, double y2) {
return sqrt(sqr(x1-x2) + sqr(y1-y2));
}
static double pointDistance(DoublePt a, DoublePt b) {
return pointDistance(a.x, a.y, b.x, b.y);
}
static DoublePt blendDoublePts(DoublePt x, DoublePt y, double yish) {
double xish = 1-yish;
return new DoublePt(x.x*xish+y.x*yish, x.y*xish+y.y*yish);
}
static float drawArrowHead_length = 2f;
static void drawArrowHead(Graphics2D g, double x1, double y1, double x2, double y2, double size) {
if (y2 == y1 && x2 == x1) return;
Path2D.Double arrowHead = new Path2D.Double();
arrowHead.moveTo(0, 0);
double l = drawArrowHead_length*size;
arrowHead.lineTo(-size, -l);
arrowHead.lineTo(size, -l);
arrowHead.closePath();
AffineTransform tx = new AffineTransform();
double angle = Math.atan2(y2-y1, x2-x1);
tx.translate(x2, y2);
tx.rotate(angle-Math.PI/2);
AffineTransform old = g.getTransform();
g.transform(tx);
g.fill(arrowHead);
g.setTransform(old);
}
static Pt pt(int x, int y) {
return new Pt(x, y);
}
static Pt pt(int x) {
return new Pt(x, x);
}
static PCallPolicy pcallPolicyForThread() {
var policy = pcallPolicyForThread_tl().get();
if (policy != null) return policy;
return defaultPCallPolicy();
}
static long round(double d) {
return Math.round(d);
}
static String round(String s) {
return roundBracket(s);
}
static Complex round(Complex c) {
return new Complex(round(c.re), round(c.im));
}
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 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 String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return c == null ? "null" : new String(c);
}
static String str(char[] c, int offset, int count) {
return new String(c, offset, count);
}
static double floor(double d) {
return Math.floor(d);
}
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 concatLists(Iterable ... lists) {
List l = new ArrayList();
if (lists != null) for (Iterable list : lists)
addAll(l, list);
return l;
}
static List concatLists(Collection extends Iterable > lists) {
List l = new ArrayList();
if (lists != null) for (Iterable list : lists)
addAll(l, list);
return l;
}
static java.awt.Color awtColor(String hex) {
byte[] b = bytesFromHex(dropPrefix("#", hex));
return new Color(ubyteToInt(b[0]), ubyteToInt(b[1]), ubyteToInt(b[2]));
}
static Color colorFromRGBA(int rgba) {
return new Color(rgba, true);
}
static java.awt.Color colorFromHex(String hex) {
return awtColor(hex);
}
static BufferedImage whiteImage(int w, int h) {
return newBufferedImage(w, h, Color.white);
}
static BufferedImage whiteImage(int size) {
return whiteImage(size, size);
}
static BufferedImage whiteImage(WidthAndHeight size) {
return whiteImage(size.getWidth(), size.getHeight());
}
static A or(A a, A b) {
return a != null ? a : b;
}
// from: https://stackoverflow.com/questions/14416107/int-array-to-bufferedimage
// pixels are RGB pixels
static BufferedImageWithMeta intArrayToBufferedImage(int[] pixels, int w) { return intArrayToBufferedImage(pixels, w, pixels.length/w); }
static BufferedImageWithMeta intArrayToBufferedImage(int[] pixels, int w, int h) {
if (w == 0 || h == 0) return null;
int[] bitMasks = new int[]{0xFF0000, 0xFF00, 0xFF, 0xFF000000};
SinglePixelPackedSampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h, bitMasks);
DataBufferInt db = new DataBufferInt(pixels, pixels.length);
WritableRaster wr = Raster.createWritableRaster(sm, db, new Point());
return new BufferedImageWithMeta(ColorModel.getRGBdefault(), wr, false, null);
}
static BufferedImageWithMeta intArrayToBufferedImage(int w, int... pixels) {
return intArrayToBufferedImage(pixels, w);
}
static double parseDouble(String s) {
return empty(s) ? 0.0 : Double.parseDouble(s);
}
static boolean isFalse(Object o) {
return eq(false, o);
}
static Graphics2D antiAliasGraphics(BufferedImage img) {
return antiAliasOn(createGraphics(img));
}
static Map createGraphics_modulators = synchroIdentityHashMap();
static Graphics2D createGraphics(BufferedImage img) {
Graphics2D g = img.createGraphics();
Object mod = createGraphics_modulators.get(img);
if (mod != null)
callF(mod, g);
return g;
}
// mod: voidfunc(Graphics2D)
static void createGraphics_modulate(BufferedImage img, Object mod) {
mapPut2(createGraphics_modulators, img, mod);
}
static double sqrt(double x) {
return Math.sqrt(x);
}
static int sqr(int i) {
return i*i;
}
static long sqr(long l) {
return l*l;
}
static double sqr(double d) {
return d*d;
}
static float sqr(float f) {
return f*f;
}
static ThreadLocal pcallPolicyForThread_tl_tl = new ThreadLocal();
static ThreadLocal pcallPolicyForThread_tl() {
return pcallPolicyForThread_tl_tl;
}
static PCallPolicy defaultPCallPolicy = __1 -> printStackTrace(__1);
static PCallPolicy defaultPCallPolicy() {
return defaultPCallPolicy;
}
static void defaultPCallPolicy_set(PCallPolicy policy) {
defaultPCallPolicy = policy;
}
static String roundBracket(String s) {
return "(" + s + ")";
}
static String roundBracket(Object s) {
return roundBracket(str(s));
}
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
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 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(IMultiSet 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(IntSize o) { return o == null ? 0 : o.size(); }
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 byte[] bytesFromHex(String s) {
return hexToBytes(s);
}
static String dropPrefix(String prefix, String s) {
return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s;
}
static int ubyteToInt(byte b) {
return b & 0x0FF;
}
static int ubyteToInt(char c) {
return c & 0x0FF;
}
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(SynchronizedLongBuffer b) { return b == null || b.isEmpty(); }
static boolean empty(DoubleBuffer b) { return b == null || b.isEmpty(); }
static boolean empty(SynchronizedFloatBufferPresentingAsDoubles b) { return b == null || b.isEmpty(); }
static boolean empty(IDoubleBuffer b) { return b == null || b.isEmpty(); }
static boolean empty(ILongBuffer 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 boolean empty(IntSize l) { return l == null || l.size() == 0; }
static Graphics2D antiAliasOn(Graphics2D g) {
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
return g;
}
static Map synchroIdentityHashMap() {
return synchroMap(new IdentityHashMap());
}
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;
}
static void mapPut2(Map map, A key, B value) {
if (map != null && key != null)
if (value != null) map.put(key, value);
else map.remove(key);
}
static A printStackTrace(A e) {
// we go to system.out now - system.err is nonsense
if (e != null) print(getStackTrace(e));
return e;
}
static void printStackTrace() {
printStackTrace(new Throwable());
}
static void printStackTrace(String msg) {
printStackTrace(new Throwable(msg));
}
static void printStackTrace(String msg, Throwable e) {
printStackTrace(new Throwable(msg, e));
}
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 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 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 byte[] hexToBytes(String s) {
if (odd(l(s))) throw fail("Hex string has odd length: " + quote(shorten(10, s)));
int n = l(s) / 2;
byte[] bytes = new byte[n];
for (int i = 0; i < n; i++) {
int a = parseHexChar(s.charAt(i*2));
int b = parseHexChar(s.charAt(i*2+1));
if (a < 0 || b < 0)
throw fail("Bad hex byte: " + quote(substring(s, i*2, i*2+2)) + " at " + i*2 + "/" + l(s));
bytes[i] = (byte) ((a << 4) | b);
}
return bytes;
}
static String getType(Object o) {
return getClassName(o);
}
static long getFileSize(String path) {
return path == null ? 0 : new File(path).length();
}
static long getFileSize(File f) {
return f == null ? 0 : f.length();
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return Collections.synchronizedMap(map);
}
static Map newDangerousWeakHashMap() {
return _registerDangerousWeakMap(synchroMap(new WeakHashMap()));
}
// initFunction: voidfunc(Map) - is called initially, and after clearing the map
static Map newDangerousWeakHashMap(Object initFunction) {
return _registerDangerousWeakMap(synchroMap(new WeakHashMap()), initFunction);
}
static String getClassName(Object o) {
return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
}
static Object invokeMethod(Method m, Object o, Object... args) { try {
try {
return m.invoke(o, args);
} catch (InvocationTargetException e) {
throw rethrow(getExceptionCause(e));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args)));
}
} catch (Exception __e) { throw rethrow(__e); } }
static boolean call_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != l(args)) {
if (debug)
print("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++) {
Object arg = args[i];
if (!(arg == null ? !types[i].isPrimitive()
: isInstanceX(types[i], arg))) {
if (debug)
print("Bad parameter " + i + ": " + arg + " vs " + types[i]);
return false;
}
}
return true;
}
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 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 print_byThread; // special handling by thread - prefers F1
static volatile Object print_allThreads;
static volatile Object print_preprocess;
static void print() {
print("");
}
static A print(String s, A o) {
print(combinePrintParameters(s, o));
return o;
}
// slightly overblown signature to return original object...
static A print(A o) {
ping_okInCleanUp();
if (print_silent) return o;
String s = o + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
try {
Object f = getThreadLocal(print_byThread_dontCreate());
if (f == null) f = print_allThreads;
if (f != null)
// We do need the general callF machinery here as print_byThread is sometimes shared between modules
if (isFalse(
f instanceof F1 ? ((F1) f).get(s) :
callF(f, s))) return;
} catch (Throwable e) {
System.out.println(getStackTrace(e));
}
print_raw(s);
}
static void print_raw(String s) {
if (print_preprocess != null) s = (String) callF(print_preprocess, s);
s = fixNewLines(s);
Appendable loc = local_log;
Appendable buf = print_log;
int loc_max = print_log_max;
if (buf != loc && buf != null) {
print_append(buf, s, print_log_max);
loc_max = local_log_max;
}
if (loc != null)
print_append(loc, s, loc_max);
if (printAlsoToSystemOut)
System.out.print(s);
vmBus_send("printed", mc(), s);
}
static void print_autoRotate() {
}
static String getStackTrace(Throwable throwable) {
lastException(throwable);
return getStackTrace_noRecord(throwable);
}
static String getStackTrace_noRecord(Throwable throwable) {
StringWriter writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
return hideCredentials(writer.toString());
}
static String getStackTrace() {
return getStackTrace_noRecord(new Throwable());
}
static String getStackTrace(String msg) {
return getStackTrace_noRecord(new Throwable(msg));
}
static Iterator emptyIterator() {
return Collections.emptyIterator();
}
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 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(IntRange r) { return !empty(r); }
static boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; }
static boolean nempty(MultiSet ms) { return ms != null && !ms.isEmpty(); }
static boolean nempty(IntSize l) { return l != null && l.size() != 0; }
static Object swing(Object f) {
return swingAndWait(f);
}
static void swing(Runnable f) {
swingAndWait(f);
}
static A swing(F0 f) {
return (A) swingAndWait(f);
}
static A swing(IF0 f) {
return (A) swingAndWait(f);
}
static A revalidate(final A c) {
if (c == null || !c.isShowing()) return c;
{ swing(() -> {
// magic combo to actually relayout and repaint
c.revalidate();
c.repaint();
}); }
return c;
}
static void revalidate(JFrame f) { revalidate((Component) f); }
static void revalidate(JInternalFrame f) { revalidate((Component) f); }
// 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(char[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (var i : a) l.add(i);
return l;
}
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);
}
static boolean odd(int i) {
return (i & 1) != 0;
}
static boolean odd(long i) {
return (i & 1) != 0;
}
static boolean odd(BigInteger i) { return odd(toInt(i)); }
static String quote(Object o) {
if (o == null) return "null";
return quote(str(o));
}
static String quote(String s) {
if (s == null) return "null";
StringBuilder out = new StringBuilder((int) (l(s)*1.5+2));
quote_impl(s, out);
return out.toString();
}
static void quote_impl(String s, StringBuilder out) {
out.append('"');
int l = s.length();
for (int i = 0; i < l; i++) {
char c = s.charAt(i);
if (c == '\\' || c == '"')
out.append('\\').append(c);
else if (c == '\r')
out.append("\\r");
else if (c == '\n')
out.append("\\n");
else if (c == '\t')
out.append("\\t");
else if (c == '\0')
out.append("\\0");
else
out.append(c);
}
out.append('"');
}
static int shorten_default = 100;
static String shorten(CharSequence s) { return shorten(s, shorten_default); }
static String shorten(CharSequence s, int max) {
return shorten(s, max, "...");
}
static String shorten(CharSequence s, int max, String shortener) {
if (s == null) return "";
if (max < 0) return str(s);
return s.length() <= max ? str(s) : subCharSequence(s, 0, min(s.length(), max-l(shortener))) + shortener;
}
static String shorten(int max, CharSequence s) { return shorten(s, max); }
static int parseHexChar(char c) {
if (c >= '0' && c <= '9') return charDiff(c, '0');
if (c >= 'a' && c <= 'f') return charDiff(c, 'a')+10;
if (c >= 'A' && c <= 'F') return charDiff(c, 'A')+10;
return -1;
}
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);
}
static String substring(String s, IntRange r) {
return r == null ? null : substring(s, r.start, r.end);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
static AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) {
return print_byThread().get() == null ? tempInterceptPrint(f) : null;
}
static Map synchroHashMap() {
return synchronizedMap(new HashMap());
}
static List _registerDangerousWeakMap_preList;
static A _registerDangerousWeakMap(A map) {
return _registerDangerousWeakMap(map, null);
}
static A _registerDangerousWeakMap(A map, Object init) {
callF(init, map);
if (init instanceof String) {
final String f = (String) init;
init = new VF1() { public void get(Map map) { try { callMC(f, map) ; } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "callMC(f, map)"; }};
}
if (javax() == null) {
// We're in class init
if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList();
_registerDangerousWeakMap_preList.add(pair(map, init));
return map;
}
call(javax(), "_registerDangerousWeakMap", map, init);
return map;
}
static void _onLoad_registerDangerousWeakMap() {
assertNotNull(javax());
if (_registerDangerousWeakMap_preList == null) return;
for (Pair p : _registerDangerousWeakMap_preList)
_registerDangerousWeakMap(p.a, p.b);
_registerDangerousWeakMap_preList = null;
}
static Throwable getExceptionCause(Throwable e) {
Throwable c = e.getCause();
return c != null ? c : e;
}
static String joinWithSpace(Iterable c) {
return join(" ", c);
}
static String joinWithSpace(Object... c) {
return join(" ", c);
}
static List classNames(Collection l) {
return getClassNames(l);
}
static List classNames(Object[] l) {
return getClassNames(asList(l));
}
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 void vmBus_send(String msg, Object... args) {
Object arg = vmBus_wrapArgs(args);
pcallFAll_minimalExceptionHandling(vm_busListeners_live(), msg, arg);
pcallFAll_minimalExceptionHandling(vm_busListenersByMessage_live().get(msg), msg, arg);
}
static void vmBus_send(String msg) {
vmBus_send(msg, (Object) null);
}
static String combinePrintParameters(String s, Object o) {
return (endsWithLetterOrDigit(s) ? s + ": " : s) + o;
}
static void ping_okInCleanUp() {
if (ping_pauseAll || ping_anyActions)
ping_impl(true);
}
// this syntax should be removed...
static Object getThreadLocal(Object o, String name) {
ThreadLocal t = (ThreadLocal) (getOpt(o, name));
return t != null ? t.get() : null;
}
static A getThreadLocal(ThreadLocal tl) {
return tl == null ? null : tl.get();
}
static A getThreadLocal(ThreadLocal tl, A defaultValue) {
return or(getThreadLocal(tl), defaultValue);
}
static ThreadLocal print_byThread_dontCreate() {
return print_byThread;
}
static String fixNewLines(String s) {
int i = indexOf(s, '\r');
if (i < 0) return s;
int l = s.length();
StringBuilder out = new StringBuilder(l);
out.append(s, 0, i);
for (; i < l; i++) {
char c = s.charAt(i);
if (c != '\r')
out.append(c);
else {
out.append('\n');
if (i+1 < l && s.charAt(i+1) == '\n') ++i;
}
}
return out.toString();
}
static void print_append(Appendable buf, String s, int max) { try {
synchronized(buf) {
buf.append(s);
if (buf instanceof StringBuffer)
rotateStringBuffer(((StringBuffer) buf), max);
else if (buf instanceof StringBuilder)
rotateStringBuilder(((StringBuilder) buf), max);
}
} catch (Exception __e) { throw rethrow(__e); } }
static Class mc() {
return main.class;
}
// PersistableThrowable doesn't hold GC-disturbing class references in backtrace
static volatile PersistableThrowable lastException_lastException;
static PersistableThrowable lastException() {
return lastException_lastException;
}
static void lastException(Throwable e) {
lastException_lastException = persistableThrowable(e);
}
static String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); }
static String hideCredentials(String url) {
try {
if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url;
} catch (Throwable e) {
print("HideCredentials", e);
}
return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2=");
}
static String hideCredentials(Object o) {
return hideCredentials(str(o));
}
static void swingAndWait(Runnable r) { try {
if (isAWTThread())
r.run();
else {
r = addThreadInfoToRunnable(r);
executingSwingCode(r);
EventQueue.invokeAndWait(r);
}
} catch (Exception __e) { throw rethrow(__e); } }
static Object swingAndWait(Object f) {
if (isAWTThread())
return callF(f);
else {
Var result = new Var();
swingAndWait(new Runnable() { public void run() { try {
result.set(callF(f));
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "result.set(callF(f));"; }});
return result.get();
}
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
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 CharSequence subCharSequence(CharSequence s, int x) {
return subCharSequence(s, x, s == null ? 0 : s.length());
}
static CharSequence subCharSequence(CharSequence 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.subSequence(x, y);
}
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 > A min(A a, A b) {
return cmp(a, b) <= 0 ? a : b;
}
static int charDiff(char a, char b) {
return (int) a-(int) b;
}
static int charDiff(String a, char b) {
return charDiff(stringToChar(a), b);
}
static int strL(String s) {
return s == null ? 0 : s.length();
}
static int lCharSequence(CharSequence s) {
return s == null ? 0 : s.length();
}
static ThreadLocal print_byThread() {
synchronized(print_byThread_lock) {
if (print_byThread == null)
print_byThread = new ThreadLocal();
}
return print_byThread;
}
// f can return false to suppress regular printing
// call print_raw within f to actually print something
static AutoCloseable tempInterceptPrint(F1 f) {
return tempSetThreadLocal(print_byThread(), f);
}
static Map synchronizedMap() {
return synchroMap();
}
static Map synchronizedMap(Map map) {
return synchroMap(map);
}
static HashMap> callMC_cache = new HashMap();
static String callMC_key;
static Method callMC_value;
// varargs assignment fixer for a single string array argument
static Object callMC(String method, String[] arg) {
return callMC(method, new Object[] {arg});
}
static Object callMC(String method, Object... args) { try {
Method me;
if (callMC_cache == null) callMC_cache = new HashMap(); // initializer time workaround
synchronized(callMC_cache) {
me = method == callMC_key ? callMC_value : null;
}
if (me != null) try {
return invokeMethod(me, null, args);
} catch (IllegalArgumentException e) {
throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e);
}
List m;
synchronized(callMC_cache) {
m = callMC_cache.get(method);
}
if (m == null) {
if (callMC_cache.isEmpty()) {
callMC_makeCache();
m = callMC_cache.get(method);
}
if (m == null) throw fail("Method named " + method + " not found in main");
}
int n = m.size();
if (n == 1) {
me = m.get(0);
synchronized(callMC_cache) {
callMC_key = method;
callMC_value = me;
}
try {
return invokeMethod(me, null, args);
} catch (IllegalArgumentException e) {
throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e);
}
}
for (int i = 0; i < n; i++) {
me = m.get(i);
if (call_checkArgs(me, args, false))
return invokeMethod(me, null, args);
}
throw fail("No method called " + method + " with arguments (" + joinWithComma(getClasses(args)) + ") found in main");
} catch (Exception __e) { throw rethrow(__e); } }
static void callMC_makeCache() {
synchronized(callMC_cache) {
callMC_cache.clear();
Class _c = (Class) mc(), c = _c;
while (c != null) {
for (Method m : c.getDeclaredMethods())
if ((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) {
makeAccessible(m);
multiMapPut(callMC_cache, m.getName(), m);
}
c = c.getSuperclass();
}
}
}
static Class javax() {
return getJavaX();
}
static List synchroList() {
return synchroList(new ArrayList ());
}
static List synchroList(List l) {
return Collections.synchronizedList(l);
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static Object call(Object o) {
return callF(o);
}
// varargs assignment fixer for a single string array argument
static Object call(Object o, String method, String[] arg) {
return call(o, method, new Object[] {arg});
}
static Object call(Object o, String method, Object... args) {
//ret call_cached(o, method, args);
return call_withVarargs(o, method, args);
}
static A assertNotNull(A a) {
assertTrue(a != null);
return a;
}
static A assertNotNull(String msg, A a) {
assertTrue(msg, a != null);
return a;
}
static A assertNotNull(Scorer scorer, String msg, A a) {
if (scorer == null) return assertNotNull(msg, a);
if (a == null) {
print("BAD - " + msg + " is null: " + a);
scorer.add(false);
} else {
print("OK, " + msg + " not null: " + a);
scorer.add(true);
}
return a;
}
public static String join(String glue, Iterable strings) {
if (strings == null) return "";
if (strings instanceof Collection) {
if (((Collection) strings).size() == 1) return strOrEmpty(first((Collection) strings));
}
StringBuilder buf = new StringBuilder();
Iterator i = strings.iterator();
if (i.hasNext()) {
buf.append(strOrEmpty(i.next()));
while (i.hasNext())
buf.append(glue).append(strOrEmpty(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 List getClassNames(Collection l) {
List out = new ArrayList();
if (l != null) for (Object o : l)
out.add(o == null ? null : getClassName(o));
return out;
}
static Object vmBus_wrapArgs(Object... args) {
return empty(args) ? null
: l(args) == 1 ? args[0]
: args;
}
static void pcallFAll_minimalExceptionHandling(Collection l, Object... args) {
if (l != null) for (Object f : cloneList(l)) { ping(); pcallF_minimalExceptionHandling(f, args); }
}
static void pcallFAll_minimalExceptionHandling(Iterator it, Object... args) {
while (it.hasNext()) { ping(); pcallF_minimalExceptionHandling(it.next(), args); }
}
static Set vm_busListeners_live_cache;
static Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache;}
static Set vm_busListeners_live_load() {
return vm_generalIdentityHashSet("busListeners");
}
static Map vm_busListenersByMessage_live_cache;
static Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache;}
static Map vm_busListenersByMessage_live_load() {
return vm_generalHashMap("busListenersByMessage");
}
static boolean endsWithLetterOrDigit(String s) {
return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length()-1));
}
// 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 Object getOpt(Object o, String field) {
return getOpt_cached(o, field);
}
static Object getOpt(String field, Object o) {
return getOpt_cached(o, field);
}
static Object getOpt_raw(Object o, String field) { try {
Field f = getOpt_findField(o.getClass(), field);
if (f == null) return null;
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
// access of static fields is not yet optimized
static Object getOpt(Class c, String field) { try {
if (c == null) return null;
Field f = getOpt_findStaticField(c, field);
if (f == null) return null;
makeAccessible(f);
return f.get(null);
} catch (Exception __e) { throw rethrow(__e); } }
static Field getOpt_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static int indexOf(List l, A a, int startIndex) {
if (l == null) return -1;
int n = l(l);
for (int i = startIndex; i < n; i++)
if (eq(l.get(i), a))
return i;
return -1;
}
static int indexOf(List l, int startIndex, A a) {
return indexOf(l, a, startIndex);
}
static int indexOf(List l, A a) {
if (l == null) return -1;
return l.indexOf(a);
}
static int indexOf(String a, String b) {
return a == null || b == null ? -1 : a.indexOf(b);
}
static int indexOf(String a, String b, int i) {
return a == null || b == null ? -1 : a.indexOf(b, i);
}
static int indexOf(String a, char b) {
return a == null ? -1 : a.indexOf(b);
}
static int indexOf(String a, int i, char b) {
return indexOf(a, b, i);
}
static int indexOf(String a, char b, int i) {
return a == null ? -1 : a.indexOf(b, i);
}
static int indexOf(String a, int i, String b) {
return a == null || b == null ? -1 : a.indexOf(b, i);
}
static int indexOf(A[] x, A a) {
int n = l(x);
for (int i = 0; i < n; i++)
if (eq(x[i], a))
return i;
return -1;
}
static int indexOf(Iterable l, A a) {
if (l == null) return -1;
int i = 0;
for (A x : l) {
if (eq(x, a))
return i;
i++;
}
return -1;
}
static void rotateStringBuffer(StringBuffer buf, int max) { try {
if (buf == null) return;
synchronized(buf) {
if (buf.length() <= max) return;
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);
}
buf.trimToSize();
}
} catch (Exception __e) { throw rethrow(__e); } }
static void rotateStringBuilder(StringBuilder buf, int max) { try {
if (buf == null) return;
synchronized(buf) {
if (buf.length() <= max) return;
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);
}
buf.trimToSize();
}
} catch (Exception __e) { throw rethrow(__e); } }
static PersistableThrowable persistableThrowable(Throwable e) {
return e == null ? null : new PersistableThrowable(e);
}
static boolean startsWithOneOf(String s, String... l) {
for (String x : l) if (startsWith(s, x)) return true; return false;
}
static boolean startsWithOneOf(String s, Matches m, String... l) {
for (String x : l) if (startsWith(s, x, m)) return true; return false;
}
static boolean isAGIBlueDomain(String domain) {
return domainIsUnder(domain, theAGIBlueDomain());
}
static String hostNameFromURL(String url) { try {
return empty(url) ? null : new URL(url).getHost();
} catch (Exception __e) { throw rethrow(__e); } }
// TODO: test if android complains about this
static boolean isAWTThread() {
if (isAndroid()) return false;
if (isHeadless()) return false;
return isAWTThread_awt();
}
static boolean isAWTThread_awt() {
return SwingUtilities.isEventDispatchThread();
}
static Runnable addThreadInfoToRunnable(final Object r) {
final Object info = _threadInfo();
return info == null ? asRunnable(r) : new Runnable() { public void run() { try { _inheritThreadInfo(info); callF(r);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_inheritThreadInfo(info); callF(r);"; }};
}
//static event executingSwingCode(Runnable code);
static transient Set> onExecutingSwingCode;
public static void onExecutingSwingCode(IVF1 f) { onExecutingSwingCode = createOrAddToSyncLinkedHashSet(onExecutingSwingCode, f); }
public static void removeExecutingSwingCodeListener(IVF1 f) { main.remove(onExecutingSwingCode, f); }
public static void executingSwingCode(Runnable code) { if (onExecutingSwingCode != null) for (var listener : onExecutingSwingCode) pcallF_typed(listener, code); }
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 char stringToChar(String s) {
if (l(s) != 1) throw fail("bad stringToChar: " + s);
return firstChar(s);
}
static AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) {
if (tl == null) return null;
final A prev = setThreadLocal(tl, a);
return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }};
}
static String joinWithComma(Iterable c) {
return join(", ", c);
}
static String joinWithComma(Object... c) {
return join(", ", c);
}
static String joinWithComma(String... c) {
return join(", ", c);
}
static String joinWithComma(Pair p) {
return p == null ? "" : joinWithComma(str(p.a), str(p.b));
}
static List getClasses(Object[] array) {
List l = emptyList(l(array));
for (Object o : array) l.add(_getClass(o));
return l;
}
static void multiMapPut(Map > map, A a, B b) {
List l = map.get(a);
if (l == null)
map.put(a, l = new ArrayList());
l.add(b);
}
static void multiMapPut(MultiMap mm, A key, B value) {
if (mm != null && key != null && value != null) mm.put(key, value);
}
static Class __javax;
static Class getJavaX() { try {
return __javax;
} catch (Exception __e) { throw rethrow(__e); } }
static void __setJavaX(Class j) {
__javax = j;
_onJavaXSet();
}
static Object call_withVarargs(Object o, String methodName, Object... args) { try {
if (o == null) return null;
if (o instanceof Class) {
Class c = (Class) o;
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findStaticMethod(methodName, args);
if (me != null)
return invokeMethod(me, null, args);
// try varargs
List methods = cache.cache.get(methodName);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
{ if (!(isStaticMethod(m))) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, null, newArgs);
}
throw fail("Method " + c.getName() + "." + methodName + "(" + formatArgumentClasses(args) + ") not found");
} else {
Class c = o.getClass();
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(methodName, args);
if (me != null)
return invokeMethod(me, o, args);
// try varargs
List methods = cache.cache.get(methodName);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, o, newArgs);
}
throw fail("Method " + c.getName() + "." + methodName + "(" + formatArgumentClasses(args) + ") not found");
}
} catch (Exception __e) { throw rethrow(__e); } }
static String strOrEmpty(Object o) {
return o == null ? "" : str(o);
}
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 A first(T3 t) {
return t == null ? null : t.a;
}
static Byte first(byte[] l) { return empty(l) ? null : l[0]; }
static Double first(double[] l) { return empty(l) ? null : l[0]; }
static byte first(ByteBuffer buf) {
return buf.get(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 first(IMultiSet a) {
return a == null ? null : first(a.keySet());
}
static ArrayList cloneList(Iterable l) {
return l instanceof Collection ? cloneList((Collection) l) : asList(l);
}
static ArrayList cloneList(Collection l) {
if (l == null) return new ArrayList();
synchronized(collectionMutex(l)) {
return new ArrayList (l);
}
}
static Object pcallF_minimalExceptionHandling(Object f, Object... args) {
try {
return callFunction(f, args);
} catch (Throwable e) {
System.out.println(getStackTrace(e));
_storeException(e);
}
return null;
}
static Set vm_generalIdentityHashSet(Object name) {
synchronized(vm_generalMap()) {
Set set = (Set) (vm_generalMap_get(name));
if (set == null)
vm_generalMap_put(name, set = syncIdentityHashSet());
return set;
}
}
static Map vm_generalHashMap(Object name) {
synchronized(vm_generalMap()) {
Map m = (Map) (vm_generalMap_get(name));
if (m == null)
vm_generalMap_put(name, m = syncHashMap());
return m;
}
}
static Map newWeakHashMap() {
return _registerWeakMap(synchroMap(new WeakHashMap()));
}
static void newPing() {
var tl = newPing_actionTL();
Runnable action = tl == null ? null : tl.get();
{ if (action != null) action.run(); }
}
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 void failIfUnlicensed() {
assertTrue("license off", licensed());
}
static Thread currentThread() {
return Thread.currentThread();
}
//static final Map> getOpt_cache = newDangerousWeakHashMap(f getOpt_special_init);
static class getOpt_Map extends WeakHashMap {
getOpt_Map() {
if (getOpt_special == null) getOpt_special = new HashMap();
clear();
}
public void clear() {
super.clear();
//print("getOpt clear");
put(Class.class, getOpt_special);
put(String.class, getOpt_special);
}
}
static final Map> getOpt_cache =
_registerDangerousWeakMap(synchroMap(new getOpt_Map()));
static HashMap getOpt_special; // just a marker
/*static void getOpt_special_init(Map map) {
map.put(Class.class, getOpt_special);
map.put(S.class, getOpt_special);
}*/
static Map getOpt_getFieldMap(Object o) {
Class c = _getClass(o);
HashMap map = getOpt_cache.get(c);
if (map == null)
map = getOpt_makeCache(c);
return map;
}
static Object getOpt_cached(Object o, String field) { try {
if (o == null) return null;
Map map = getOpt_getFieldMap(o);
if (map == getOpt_special) {
if (o instanceof Class)
return getOpt((Class) o, field);
/*if (o instanceof S)
ret getOpt(getBot((S) 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 syncMapGet2(((DynamicObject) o).fieldValues, field);
return null;
} catch (Exception __e) { throw rethrow(__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();
if (!reflection_classesNotToScan().contains(c.getName())) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields()) {
makeAccessible(f);
String name = f.getName();
if (!map.containsKey(name))
map.put(name, f);
}
_c = _c.getSuperclass();
} while (_c != null);
}
}
if (getOpt_cache != null) getOpt_cache.put(c, map);
return map;
}
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 boolean startsWith(String a, String b) {
return a != null && a.startsWith(unnull(b));
}
static boolean startsWith(String a, char c) {
return nemptyString(a) && a.charAt(0) == c;
}
static boolean startsWith(String a, String b, Matches m) {
if (!startsWith(a, b)) return false;
if (m != null) m.m = new String[] {substring(a, strL(b))};
return true;
}
static boolean startsWith(List a, List b) {
if (a == null || listL(b) > listL(a)) return false;
for (int i = 0; i < listL(b); i++)
if (neq(a.get(i), b.get(i)))
return false;
return true;
}
static boolean domainIsUnder(String domain, String mainDomain) {
return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain);
}
static String theAGIBlueDomain() {
return "agi.blue";
}
static int isAndroid_flag;
static boolean isAndroid() {
if (isAndroid_flag == 0)
isAndroid_flag = System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0 ? 1 : -1;
return isAndroid_flag > 0;
}
static Boolean isHeadless_cache;
static boolean isHeadless() {
if (isHeadless_cache != null) return isHeadless_cache;
if (isAndroid()) return isHeadless_cache = true;
if (GraphicsEnvironment.isHeadless()) return isHeadless_cache = true;
// Also check if AWT actually works.
// If DISPLAY variable is set but no X server up, this will notice.
try {
SwingUtilities.isEventDispatchThread();
return isHeadless_cache = false;
} catch (Throwable e) { return isHeadless_cache = true; }
}
static List> _threadInfo_makers = synchroList();
static Object _threadInfo() {
if (empty(_threadInfo_makers)) return null;
HashMap map = new HashMap();
pcallFAll(_threadInfo_makers, map);
return map;
}
static Runnable asRunnable(Object o) {
return toRunnable(o);
}
static void _inheritThreadInfo(Object info) {
_threadInheritInfo(info);
}
static Set createOrAddToSyncLinkedHashSet(Set set, A a) {
if (set == null) set = syncLinkedHashSet();
set.add(a);
return set;
}
static Class main() {
return getMainClass();
}
static void remove(List l, int i) {
if (l != null && i >= 0 && i < l(l))
l.remove(i);
}
static void remove(Collection l, A a) {
if (l != null) l.remove(a);
}
static B remove(Map map, Object a) {
return map == null ? null : map.remove(a);
}
static void remove(BitSet bs, int i) {
bs.clear(i);
}
static A pcallF_typed(F0 f) {
try { return f == null ? null : f.get(); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static B pcallF_typed(F1 f, A a) {
try { return f == null ? null : f.get(a); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static void pcallF_typed(VF1 f, A a) {
try {
{ if (f != null) f.get(a); }
} catch (Throwable __e) { pcallFail(__e); }
}
static void pcallF_typed(IVF1 f, A a) {
try {
{ if (f != null) f.get(a); }
} catch (Throwable __e) { pcallFail(__e); }
}
static void pcallF_typed(IVF2 f, A a, B b) {
try {
{ if (f != null) f.get(a, b); }
} catch (Throwable __e) { pcallFail(__e); }
}
static Object pcallF_typed(Runnable r) {
try { { if (r != null) r.run(); } } catch (Throwable __e) { pcallFail(__e); } return null;
}
static A pcallF_typed(IF0 f) {
try { return f == null ? null : f.get(); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static B pcallF_typed(IF1 f, A a) {
try { return f == null ? null : f.get(a); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static boolean emptyString(String s) {
return s == null || s.length() == 0;
}
static char firstChar(String s) {
return s.charAt(0);
}
static A setThreadLocal(ThreadLocal tl, A value) {
if (tl == null) return null;
A old = tl.get();
tl.set(value);
return old;
}
static Class> _getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null; // could optimize this
}
}
static Class _getClass(Object o) {
return o == null ? null
: o instanceof Class ? (Class) o : o.getClass();
}
static Class _getClass(Object realm, String name) {
try {
return classLoaderForObject(realm).loadClass(classNameToVM(name));
} catch (ClassNotFoundException e) {
return null; // could optimize this
}
}
static void _onJavaXSet() {}
static final Map callOpt_cache = newDangerousWeakHashMap();
static Object callOpt_cached(Object o, String methodName, Object... args) { try {
if (o == null) return null;
if (o instanceof Class) {
Class c = (Class) o;
_MethodCache cache = callOpt_getCache(c);
// TODO: (super-rare) case where method exists static and non-static
// with different args
Method me = cache.findMethod(methodName, args);
if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null;
return invokeMethod(me, null, args);
} else {
Class c = o.getClass();
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(methodName, args);
if (me == null) return null;
return invokeMethod(me, o, args);
}
} catch (Exception __e) { throw rethrow(__e); } }
// no longer synchronizes! (see #1102990)
static _MethodCache callOpt_getCache(Class c) {
_MethodCache cache = callOpt_cache.get(c);
if (cache == null)
callOpt_cache.put(c, cache = new _MethodCache(c));
return cache;
}
static boolean isStaticMethod(Method m) {
return methodIsStatic(m);
}
static Object[] massageArgsForVarArgsCall(Executable m, Object[] args) {
Class>[] types = m.getParameterTypes();
int n = types.length-1, nArgs = l(args);
if (nArgs < n) return null;
for (int i = 0; i < n; i++)
if (!argumentCompatibleWithType(args[i], types[i]))
return null;
Class varArgType = types[n].getComponentType();
for (int i = n; i < nArgs; i++)
if (!argumentCompatibleWithType(args[i], varArgType))
return null;
Object[] newArgs = new Object[n+1];
arraycopy(args, 0, newArgs, 0, n);
// TODO: optimize
int nVarArgs = nArgs-n;
Object varArgs = Array.newInstance(varArgType, nVarArgs);
for (int i = 0; i < nVarArgs; i++)
Array.set(varArgs, i, args[n+i]);
newArgs[n] = varArgs;
return newArgs;
}
static String formatArgumentClasses(Object[] args) {
return joinWithComma(map(__22 -> getClassName(__22), args));
}
static Pair mapEntryToPair(Map.Entry e) {
return e == null ? null : pair(e.getKey(), e.getValue());
}
static Set> entrySet(Map map) {
return _entrySet(map);
}
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);
}
// TODO: JDK 17!! ?? No! Yes? Yes!!
static Object collectionMutex(List l) {
return l;
}
static Object collectionMutex(Object o) {
if (o instanceof List) return o;
// TODO: actually use our own maps so we can get the mutex properly
String c = className(o);
return o;
}
static Object callFunction(Object f, Object... args) {
return callF(f, args);
}
static Throwable _storeException_value;
static void _storeException(Throwable e) {
_storeException_value = e;
}
static Map vm_generalMap_map;
static Map vm_generalMap() {
if (vm_generalMap_map == null)
vm_generalMap_map = (Map) get(javax(), "generalMap");
return vm_generalMap_map;
}
static Object vm_generalMap_get(Object key) {
return vm_generalMap().get(key);
}
static Object vm_generalMap_put(Object key, Object value) {
return mapPutOrRemove(vm_generalMap(), key, value);
}
static Set syncIdentityHashSet() {
return (Set) synchronizedSet(identityHashSet());
}
static Map syncHashMap() {
return synchroHashMap();
}
static List _registerWeakMap_preList;
static A _registerWeakMap(A map) {
if (javax() == null) {
// We're in class init
if (_registerWeakMap_preList == null) _registerWeakMap_preList = synchroList();
_registerWeakMap_preList.add(map);
return map;
}
try {
call(javax(), "_registerWeakMap", map);
} catch (Throwable e) {
printException(e);
print("Upgrade JavaX!!");
}
return map;
}
static void _onLoad_registerWeakMap() {
assertNotNull(javax());
if (_registerWeakMap_preList == null) return;
for (Object o : _registerWeakMap_preList)
_registerWeakMap(o);
_registerWeakMap_preList = null;
}
static x30_pkg.x30_util.BetterThreadLocal newPing_actionTL;
static x30_pkg.x30_util.BetterThreadLocal newPing_actionTL() {
if (newPing_actionTL == null)
newPing_actionTL = vm_generalMap_getOrCreate("newPing_actionTL",
() -> {
Runnable value = (Runnable) (callF_gen(vm_generalMap_get("newPing_valueForNewThread")));
var tl = new x30_pkg.x30_util.BetterThreadLocal();
tl.set(value);
return tl;
});
return newPing_actionTL;
}
static volatile boolean licensed_yes = true;
static boolean licensed() {
if (!licensed_yes) return false;
ping_okInCleanUp();
return true;
}
static void licensed_off() {
licensed_yes = false;
}
static void clear(Collection c) {
if (c != null) c.clear();
}
static void clear(Map map) {
if (map != null) map.clear();
}
static void put(Map map, A a, B b) {
if (map != null) map.put(a, b);
}
static void put(List l, int i, A a) {
if (l != null && i >= 0 && i < l(l)) l.set(i, a);
}
static B syncMapGet2(Map map, A a) {
if (map == null) return null;
synchronized(collectionMutex(map)) {
return map.get(a);
}
}
static B syncMapGet2(A a, Map map) {
return syncMapGet2(map, a);
}
static boolean isSubtypeOf(Class a, Class b) {
return a != null && b != null && b.isAssignableFrom(a); // << always hated that method, let's replace it!
}
static Set reflection_classesNotToScan_value = litset(
"jdk.internal.loader.URLClassPath"
);
static Set reflection_classesNotToScan() {
return reflection_classesNotToScan_value;
}
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 boolean nemptyString(String s) {
return s != null && s.length() > 0;
}
static int listL(Collection l) {
return l == null ? 0 : l.size();
}
static boolean neq(Object a, Object b) {
return !eq(a, b);
}
static boolean eqic(String a, String b) {
if ((a == null) != (b == null)) return false;
if (a == null) return true;
return a.equalsIgnoreCase(b);
}
static boolean eqic(Symbol a, Symbol b) {
return eq(a, b);
}
static boolean eqic(Symbol a, String b) {
return eqic(asString(a), b);
}
static boolean eqic(char a, char b) {
if (a == b) return true;
char u1 = Character.toUpperCase(a);
char u2 = Character.toUpperCase(b);
if (u1 == u2) return true;
return Character.toLowerCase(u1) == Character.toLowerCase(u2);
}
static boolean ewic(String a, String b) {
return endsWithIgnoreCase(a, b);
}
static boolean ewic(String a, String b, Matches m) {
return endsWithIgnoreCase(a, b, m);
}
static void pcallFAll(Collection l, Object... args) {
if (l != null) for (Object f : cloneList(l)) pcallF(f, args);
}
static void pcallFAll(Iterator it, Object... args) {
while (it.hasNext()) pcallF(it.next(), args);
}
static Runnable toRunnable(final Object o) {
if (o == null) return null;
if (o instanceof Runnable) return (Runnable) o;
if (o instanceof String) throw fail("callF_legacy");
return new Runnable() { public void run() { try { callF(o) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; }};
}
static List> _threadInheritInfo_retrievers = synchroList();
static void _threadInheritInfo(Object info) {
if (info == null) return;
pcallFAll(_threadInheritInfo_retrievers, (Map) info);
}
static Set syncLinkedHashSet() {
return synchroLinkedHashSet();
}
static Class getMainClass() {
return mc();
}
static Class getMainClass(Object o) { try {
if (o == null) return null;
if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o;
ClassLoader cl = (o instanceof Class ? (Class) o : o.getClass()).getClassLoader();
if (cl == null) return null;
String name = mainClassNameForClassLoader(cl);
return loadClassFromClassLoader_orNull(cl, name);
} catch (Exception __e) { throw rethrow(__e); } }
static ClassLoader classLoaderForObject(Object o) {
if (o instanceof ClassLoader) return ((ClassLoader) o);
if (o == null) return null;
return _getClass(o).getClassLoader();
}
// Note: This is actually broken. Inner classes must stay with a $ separator
static String classNameToVM(String name) {
return name.replace(".", "$");
}
static boolean methodIsStatic(Method m) {
return (m.getModifiers() & Modifier.STATIC) != 0;
}
static boolean argumentCompatibleWithType(Object arg, Class type) {
return arg == null ? !type.isPrimitive() : isInstanceX(type, arg);
}
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 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 Set> _entrySet(Map map) {
return map == null ? Collections.EMPTY_SET : map.entrySet();
}
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 String className(Object o) {
return getClassName(o);
}
// 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 B mapPutOrRemove(Map map, A key, B value) {
if (map != null && key != null)
if (value != null) return map.put(key, value);
else return map.remove(key);
return null;
}
static Set synchronizedSet() {
return synchroHashSet();
}
static Set synchronizedSet(Set set) {
return Collections.synchronizedSet(set);
}
static Set identityHashSet() {
return Collections.newSetFromMap(new IdentityHashMap());
}
static A printException(A e) {
printStackTrace(e);
return e;
}
static A vm_generalMap_getOrCreate(Object key, F0 create) {
return vm_generalMap_getOrCreate(key, f0ToIF0(create));
}
static A vm_generalMap_getOrCreate(Object key, IF0 create) {
Map generalMap = vm_generalMap();
if (generalMap == null) return null; // must be x30 init
synchronized(generalMap) { // should switch to locks here
A a = (A) (vm_generalMap_get(key));
if (a == null)
vm_generalMap_put(key, a = create == null ? null : create.get());
return a;
}
}
static A callF_gen(F0 f) {
return f == null ? null : f.get();
}
static B callF_gen(F1 f, A a) {
return f == null ? null : f.get(a);
}
static A callF_gen(IF0 f) {
return f == null ? null : f.get();
}
static B callF_gen(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF_gen(A a, IF1 f) {
return f == null ? null : f.get(a);
}
static C callF_gen(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF_gen(VF1 f, A a) {
{ if (f != null) f.get(a); }
}
static void callF_gen(A a, IVF1 f) {
{ if (f != null) f.get(a); }
}
static void callF_gen(IVF1 f, A a) {
{ if (f != null) f.get(a); }
}
static Object callF_gen(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF_gen(Object f, Object... args) {
return callF(f, args);
}
static HashSet litset(A... items) {
return lithashset(items);
}
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;
}
static String asString(Object o) {
return o == null ? null : o.toString();
}
static boolean endsWithIgnoreCase(String a, String b) {
int la = l(a), lb = l(b);
return la >= lb && regionMatchesIC(a, la-lb, b, 0, lb);
}
static boolean endsWithIgnoreCase(String a, String b, Matches m) {
if (!endsWithIgnoreCase(a, b)) return false;
if (m != null)
m.m = new String[] { substring(a, 0, l(a)-l(b)) };
return true;
}
static Object pcallF(Object f, Object... args) {
return pcallFunction(f, args);
}
static A pcallF(F0 f) {
try { return f == null ? null : f.get(); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static B pcallF(F1 f, A a) {
try { return f == null ? null : f.get(a); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static void pcallF(VF1 f, A a) {
try {
{ if (f != null) f.get(a); }
} catch (Throwable __e) { pcallFail(__e); }
}
static Object pcallF(Runnable r) {
try { { if (r != null) r.run(); } } catch (Throwable __e) { pcallFail(__e); } return null;
}
static A pcallF(IF0 f) {
try { return f == null ? null : f.get(); } catch (Throwable __e) { pcallFail(__e); } return null;
}
static B pcallF(IF1 f, A a) {
try { return f == null ? null : f.get(a); } catch (Throwable __e) { pcallFail(__e); } return null;
}
// BREAKING CHANGE!
// Also NOTE: Iterators of these sync-wrapped collections
// after generally NOT thread-safe!
// TODO: change that?
static Set synchroLinkedHashSet() {
return synchronizedSet(new CompactLinkedHashSet());
}
static String mainClassNameForClassLoader(ClassLoader cl) {
return or((String) callOpt(cl, "mainClassName"), "main");
}
static Class loadClassFromClassLoader_orNull(ClassLoader cl, String name) {
try {
return cl == null ? null : cl.loadClass(name);
} catch (ClassNotFoundException e) {
return null;
}
}
// 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 List immutableEmptyList() {
return Collections.emptyList();
}
static byte[] emptyByteArray_a = new byte[0];
static byte[] emptyByteArray() { return emptyByteArray_a; }
static short[] emptyShortArray = new short[0];
static short[] emptyShortArray() { return emptyShortArray; }
static Map immutableEmptyMap() {
return Collections.emptyMap();
}
static Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
static Set synchroHashSet() {
return synchronizedSet(new HashSet ());
}
static IF0 f0ToIF0(F0 f) {
return f == null ? null : () -> f.get();
}
static HashSet lithashset(A... items) {
HashSet set = new HashSet();
for (A a : items) set.add(a);
return set;
}
static WeakHasherMap symbol_map = new WeakHasherMap(new Hasher() {
public int hashCode(Symbol symbol) { return symbol.text.hashCode(); }
public boolean equals(Symbol a, Symbol b) {
if (a == null) return b == null;
return b != null && eq(a.text, b.text);
}
});
static Symbol symbol(String s) {
if (s == null) return null;
synchronized(symbol_map) {
// TODO: avoid object creation by passing the string to findKey
Symbol symbol = new Symbol(s, true);
Symbol existingSymbol = symbol_map.findKey(symbol);
if (existingSymbol == null)
symbol_map.put(existingSymbol = symbol, true);
return existingSymbol;
}
}
static Symbol symbol(CharSequence s) {
if (s == null) return null;
if (s instanceof Symbol) return (Symbol) s;
if (s instanceof String) return symbol((String) s);
return symbol(str(s));
}
static Symbol symbol(Object o) {
return symbol((CharSequence) o);
}
static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) {
return a != null && a.regionMatches(true, offsetA, b, offsetB, len);
}
static Object pcallFunction(Object f, Object... args) {
try { return callFunction(f, args); } catch (Throwable __e) { pcallFail(__e); }
return null;
}
static Object callOpt(Object o) {
return callF(o);
}
static Object callOpt(Object o, String method, Object... args) {
return callOpt_withVarargs(o, method, args);
}
static BetterThreadLocal pingSource_tl_var = new BetterThreadLocal() {
@Override
public PingSource initialValue() {
return ping_v3_pingSourceMaker().get();
}
};
static BetterThreadLocal pingSource_tl() {
return pingSource_tl_var;
}
static Object callOpt_withVarargs(Object o, String method, Object... args) { try {
if (o == null) return null;
if (o instanceof Class) {
Class c = (Class) o;
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(method, args);
if (me == null) {
// TODO: varargs
return null;
}
if ((me.getModifiers() & Modifier.STATIC) == 0)
return null;
return invokeMethod(me, null, args);
} else {
Class c = o.getClass();
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(method, args);
if (me != null)
return invokeMethod(me, o, args);
// try varargs
List methods = cache.cache.get(method);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, o, newArgs);
}
return null;
}
} catch (Exception __e) { throw rethrow(__e); } }
static IF0 ping_v3_pingSourceMaker_cache;
static IF0 ping_v3_pingSourceMaker() { if (ping_v3_pingSourceMaker_cache == null) ping_v3_pingSourceMaker_cache = ping_v3_pingSourceMaker_load(); return ping_v3_pingSourceMaker_cache;}
static IF0 ping_v3_pingSourceMaker_load() {
return or((IF0) vm_generalMap_get("ping_v3_pingSourceMaker"), () -> null);
}
static class TickerSequence implements ByteIO, 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"
// in case the sequence is digitized
final public TickerSequence setPriceCells(PriceCells priceCells){ return priceCells(priceCells); }
public TickerSequence priceCells(PriceCells priceCells) { this.priceCells = priceCells; return this; } final public PriceCells getPriceCells(){ return priceCells(); }
public PriceCells priceCells() { return priceCells; }
PriceCells priceCells;
// are we live?
final public TickerSequence setLive(boolean live){ return live(live); }
public TickerSequence live(boolean live) { this.live = live; return this; } final public boolean getLive(){ return live(); }
public boolean live() { return live; }
boolean live = false;
// Is the data incomplete (still loading)?
final public TickerSequence setLoading(boolean loading){ return loading(loading); }
public TickerSequence loading(boolean loading) { this.loading = loading; return this; } final public boolean getLoading(){ return loading(); }
public boolean loading() { return loading; }
boolean loading = false;
ILongBuffer timestamps = new SynchronizedLongBuffer();
IDoubleBuffer prices = new SynchronizedFloatBufferPresentingAsDoubles();
// timestamp of last ticker event even though price may not
// have changed
final public TickerSequence setLastTickerEvent(long lastTickerEvent){ return lastTickerEvent(lastTickerEvent); }
public TickerSequence lastTickerEvent(long lastTickerEvent) { this.lastTickerEvent = lastTickerEvent; return this; } final public long getLastTickerEvent(){ return lastTickerEvent(); }
public long lastTickerEvent() { return lastTickerEvent; }
long lastTickerEvent;
final public TickerSequence setEpsilon(double epsilon){ return epsilon(epsilon); }
public TickerSequence epsilon(double epsilon) { this.epsilon = epsilon; return this; } final public double getEpsilon(){ return epsilon(); }
public double epsilon() { return epsilon; }
double epsilon = 1e-6;
transient Set> onPricePointAdded;
public TickerSequence onPricePointAdded(IVF1 f) { onPricePointAdded = createOrAddToSyncLinkedHashSet(onPricePointAdded, f); return this; }
public TickerSequence removePricePointAddedListener(IVF1 f) { main.remove(onPricePointAdded, f); return this; }
public void pricePointAdded(long timestamp) { if (onPricePointAdded != null) for (var listener : onPricePointAdded) pcallF_typed(listener, timestamp); }
transient Set onNewTickerEvent;
public TickerSequence onNewTickerEvent(Runnable r) { onNewTickerEvent = createOrAddToSyncLinkedHashSet(onNewTickerEvent, r); return this; }
public TickerSequence removeNewTickerEventListener(Runnable r) { main.remove(onNewTickerEvent, r); return this; }
public void newTickerEvent() { if (onNewTickerEvent != null) for (var listener : onNewTickerEvent) pcallF_typed(listener); }
TickerSequence(String market) {
this.market = market;}
void addIfPriceChanged(double price, Timestamp timestamp) {
addIfPriceChanged(price, toLong(timestamp));
}
synchronized void addIfPriceChanged(double price, long timestamp) {
if (isEmpty() || differentByEpsilonRatio(prices.last(), price, epsilon))
add(price, timestamp);
updateTickerEvent(timestamp);
}
void updateTickerEvent(long timestamp) {
if (timestamp > lastTickerEvent) {
lastTickerEvent(timestamp);
newTickerEvent();
}
}
final void addPrice(double price, long timestamp){ add(price, timestamp); }
synchronized void add(double price, long timestamp) {
timestamps.add(timestamp);
prices.add(price);
pricePointAdded(timestamp);
updateTickerEvent(timestamp);
}
synchronized void add(double[] prices, long[] timestamps) {
assertEquals(l(prices), l(timestamps));
if (empty(prices)) return;
// TODO: call pricePointAdded?
this.prices.addAll(asList(prices));
this.timestamps.addAll(asList(timestamps));
lastTickerEvent = max(lastTickerEvent, endTime());
}
synchronized void add(TickerSequence ticker) {
add(ticker.prices.toArray(), ticker.timestamps.toArray());
}
synchronized public String toString() {
return commaCombine(
spaceCombine(
"Ticker",
market,
priceCells == null ? null : roundBracket(priceCells)),
formatDays(duration()),
n2(l(prices), "price point"),
timeRange()
);
}
public synchronized TickerSequence clone() {
return subSequence(0, size());
}
TickerSequence emptyClone() {
return new TickerSequence().market(market);
}
synchronized TickerSequence subSequence(int start) { return subSequence(start, size()); }
synchronized TickerSequence subSequence(int start, int end) {
var s = emptyClone();
s.add(
cloneSubDoubleArray(prices.toArray(), start, end),
cloneSubLongArray(timestamps.toArray(), start, end));
return s;
}
synchronized TickerSequence cutOffAfterSeconds(double seconds) {
int idx = indexOfTimestamp(startTime()+secondsToMS(seconds));
return subSequence(0, idx);
}
TickerSequence dropFirstDays(double days) {
return subSequenceFromTimestamp(startTime()+daysToMS(days));
}
TickerSequence takeFirstDays(double days) {
return cutOffAfterSeconds(daysToSeconds(days));
}
TickerSequence takeFirstHours(double days) {
return cutOffAfterSeconds(hoursToSeconds(days));
}
TickerSequence takeLastDays(double days) {
return subSequenceFromTimestamp(endTime()-daysToMS(days));
}
TickerSequence takeLastHours(double hours) {
return takeLastDays(hoursToDays(hours));
}
TickerSequence takeLastMinutes(double minutes) {
return takeLastDays(minutesToDays(minutes));
}
synchronized TickerSequence subSequenceByTimestamps(long from, long to) {
int idx1 = indexOfTimestamp(from);
int idx2 = indexOfTimestamp(to);
return subSequence(idx1, idx2);
}
synchronized TickerSequence subSequenceFromTimestamp(long from) {
return subSequence(indexOfTimestamp(from));
}
synchronized TickerSequence subSequenceToTimestamp(long to) {
return subSequence(0, indexOfTimestamp(to));
}
// TODO: shouldn't we subtract one here?
synchronized int indexOfTimestamp(double ts) {
return binarySearch_insertionPoint(timestamps.asVirtualList(), lround(ts));
}
synchronized long nextTimestamp(double ts) {
return getTimestamp(indexOfTimestamp(ts)+1);
}
synchronized double priceAtTimestamp(double ts) {
return getPrice(indexOfTimestamp(ts));
}
public int size() { return l(prices); }
public boolean isEmpty() { return size() == 0; }
synchronized TimestampRange timeRange() {
return isEmpty() ? null : new TimestampRange(startTime(), endTime());
}
Duration duration() {
return main.duration(timeRange());
}
synchronized long startTime() { return empty(timestamps) ? 0 : first(timestamps); }
synchronized long endTime() { return empty(timestamps) ? 0 : last(timestamps); }
synchronized double getPrice(int i) {
return isEmpty() ? Double.NaN : prices.get(clampToLength(size(), i));
}
synchronized long getTimestamp(int i) {
return isEmpty() ? 0 : timestamps.get(clampToLength(size(), i));
}
synchronized TickerSequence removePlateaus() {
var seq = emptyClone();
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.trimToSize();
}
synchronized TickerSequence removeZeros() {
if (!prices.contains(0)) return this;
var seq = emptyClone();
int n = size();
for (int i = 0; i < n; i++) {
var value = getPrice(i);
if (value != 0) {
seq.prices.add(value);
seq.timestamps.add(getTimestamp(i));
}
}
return seq.trimToSize();
}
synchronized TickerSequence alignTimestamps(int interval) {
var seq = emptyClone();
int n = size();
for (int i = 0; i < n; i++) {
var value = getPrice(i);
long time = roundDownTo(interval, getTimestamp(i));
if (time != seq.endTime())
seq.addIfPriceChanged(value, time);
}
return seq.trimToSize();
}
TickerSequence trimToSize() {
prices.trimToSize();
timestamps.trimToSize();
return this;
}
double minPrice() { return doubleMin(prices.toArray()); }
double maxPrice() { return doubleMax(prices.toArray()); }
DoubleRange priceRange() { return doubleRange(minPrice(), maxPrice()); }
synchronized double firstPrice() { return empty(prices) ? Double.NaN : prices.first(); }
synchronized double lastPrice() { return empty(prices) ? Double.NaN : prices.last(); }
synchronized TickerPoint lastPoint() {
return new TickerPoint(this, endTime());
}
static Pattern reBestAsk = regexp("\"bestAsk\":([0-9\\.]+)");
static Pattern reSystemTime = regexp("\"systemTime\":(\\d+)");
// parse line from a .ticker file
synchronized void addJSONLine_fast(String line) {
long time = toLong(regexpFirstGroup(reSystemTime, line));
if (time > lastTickerEvent) {
double price = toDouble(regexpFirstGroup(reBestAsk, line));
if (price != 0)
addIfPriceChanged(price, time);
}
}
transient IVF1 addJSONLine;
void addJSONLine(String line) { if (addJSONLine != null) addJSONLine.get(line); else addJSONLine_base(line); }
final void addJSONLine_fallback(IVF1 _f, String line) { if (_f != null) _f.get(line); else addJSONLine_base(line); }
void addJSONLine_base(String line) {
addJSONLine_fast(line);
}
synchronized void addJSONLine_slow(String line) {
Map data = parseJSONMap(line);
double price = toDouble(data.get("bestAsk"));
long time = toLong(data.get("systemTime"));
if (time > lastTickerEvent)
addIfPriceChanged(price, time);
}
final UpDownSequence upDownSequence(){ return toUpDownSequence(); }
UpDownSequence toUpDownSequence() { return toUpDownSequence(priceCells); }
final UpDownSequence upDownSequence(PriceCells cells){ return toUpDownSequence(cells); }
UpDownSequence toUpDownSequence(PriceCells cells) {
if (cells == null) return null;
var dig = digitize(new PriceDigitizer2(cells));
List cellNumbers = dig.roundedCellNumbers();
return UpDownSequence.fromInts(cellNumbers);
}
TickerSequence digitizeToPercent(double cellSizeInPercent) { return digitizeToPercent(firstPrice(), cellSizeInPercent); }
TickerSequence digitizeToPercent(double basePrice, double cellSizeInPercent) {
if (isEmpty()) return this;
return digitize(geometricPriceDigitizer(basePrice, cellSizeInPercent));
}
TickerSequence digitize(PriceDigitizer2 digitizer) {
var seq = emptyClone();
seq.priceCells(digitizer.priceCells());
int n = size();
for (int i = 0; i < n; i++) {
seq.addIfPriceChanged(digitizer.digitize(getPrice(i)), getTimestamp(i));
}
return seq.trimToSize();
}
List pricePoints() {
return listFromFunction(__56 -> getPricePoint(__56), size());
}
synchronized PricePoint getPricePoint(int idx) {
return idx >= 0 && idx < size() ? new PricePoint(timestamps.get(idx), prices.get(idx)) : null;
}
PricePoint firstPricePoint() { return getPricePoint(0); }
synchronized PricePoint lastPricePoint() { return getPricePoint(size()-1); }
List roundedCellNumbers() {
return map(__23 -> iround(__23), cellNumbers());
}
List cellNumbers() {
if (priceCells == null) return null;
int n = size();
DoubleBuffer buf = new DoubleBuffer(n);
for (int i = 0; i < n; i++)
buf.add(priceCells.toCellNumber(getPrice(i)));
return buf.asVirtualList();
}
TickerSequence toCellNumbers() {
if (priceCells == null) return null;
TickerSequence seq = new TickerSequence();
seq.market(market + " cell numbers " + roundBracket(priceCells));
int n = size();
for (int i = 0; i < n; i++)
seq.add(priceCells.toCellNumber(getPrice(i)), getTimestamp(i));
return seq.trimToSize();
}
void dropLastPricePoint() {
if (isEmpty()) return;
prices.popLast();
timestamps.popLast();
lastTickerEvent = endTime();
newTickerEvent();
}
TickerSequence marketIfEmpty(String market) {
if (empty(this.market)) market(market);
return this;
}
TickerSequence legacyCompact() {
if (!(prices instanceof SynchronizedFloatBufferPresentingAsDoubles))
prices = new SynchronizedFloatBufferPresentingAsDoubles(prices.toArray());
return this;
}
// msUnit = how many milliseconds to group into one
boolean compactTimestamps() { return compactTimestamps(20); }
boolean compactTimestamps(long msUnit) {
if (!(timestamps instanceof SynchronizedLongBufferStoredAsLinearInts)) {
timestamps = new SynchronizedLongBufferStoredAsLinearInts(roundDownTo(msUnit, startTime()), msUnit, timestamps);
return true;
}
return false;
}
double averageTimeStep() {
return doubleRatio(endTime()-startTime(), size()-1);
}
public void write(ByteHead head) {
head.writeString(market);
SynchronizedLongBufferStoredAsLinearInts timestamps = (SynchronizedLongBufferStoredAsLinearInts) (this.timestamps);
head.writeLong(timestamps.base);
head.writeLong(timestamps.factor);
int n = size();
head.writeInt(n);
for (int i = 0; i < n; i++) {
head.writeInt(timestamps.getRaw(i));
head.writeFloat((float) prices.get(i));
}
}
public void readWrite(ByteHead head) {
if (head.readMode()) readImpl(head);
if (head.writeMode()) write(head);
}
static TickerSequence read(ByteHead head) {
TickerSequence t = new TickerSequence();
if (!t.readImpl(head)) return null;
return t;
}
boolean readImpl(ByteHead head) {
market = head.readString();
if (head.eof()) return false;
long base = head.readLong();
long factor = head.readLong();
//printVars(+market, +base, +factor);
var timestamps = new SynchronizedLongBufferStoredAsLinearInts (base, factor);
this.timestamps = timestamps;
int n = head.readInt();
for (int i = 0; i < n; i++) {
int time = head.readInt();
if (head.eof()) break;
timestamps.addRaw(time);
prices.add(head.readFloat());
}
trimToSize();
return true;
}
TickerSequence loadJSONFile(File f) {
var it = linesFromFile(f); try {
for (var line : it) { try { addJSONLine(line); } catch (Throwable __e) { pcallFail(__e); }}
return trimToSize();
} finally { _close(it); }}
synchronized void insertAt(int idx, TickerSequence ticker) {
prices.insertAt(idx, ticker.prices.toArray());
timestamps.insertAt(idx, ticker.timestamps.toArray());
}
}
static abstract class VF1 implements IVF1 {
public abstract void get(A a);
}
// immutable, has strong refs
// Do not run in a synchronized block - it goes wrong in the presence
// of elaborate classloaders (like in Gazelle BEA)
// see #1102990 and #1102991
final static class _MethodCache {
final Class c;
final HashMap> cache = new HashMap();
_MethodCache(Class c) {
this.c = c; _init(); }
void _init() {
Class _c = c;
java.lang.Module myModule = getClass().getModule();
boolean anyHiddenClasses = false;
while (_c != null) {
boolean exported = classIsExportedTo(_c, myModule);
if (!exported)
anyHiddenClasses = true;
else
for (Method m : _c.getDeclaredMethods())
if ((anyHiddenClasses || !isAbstract(m))
&& !reflection_isForbiddenMethod(m))
multiMapPut(cache, m.getName(), makeAccessible(m));
_c = _c.getSuperclass();
}
// add default methods - this might lead to a duplication
// because the overridden method is also added, but it's not
// a problem except for minimal performance loss.
// If any classes in the hierarchy were inaccessible, we add
// all interface methods (see test_callForbiddenMethodByReflection for a test)
for (Class intf : allInterfacesImplementedBy(c))
for (Method m : intf.getDeclaredMethods())
if ((anyHiddenClasses || m.isDefault()) && !reflection_isForbiddenMethod(m))
multiMapPut(cache, m.getName(), makeAccessible(m));
}
// Returns only matching methods
Method findMethod(String method, Object[] args) { try {
List m = cache.get(method);
if (m == null) return null;
int n = m.size();
for (int i = 0; i < n; i++) {
Method me = m.get(i);
if (call_checkArgs(me, args, false))
return me;
}
return null;
} catch (Exception __e) { throw rethrow(__e); } }
Method findStaticMethod(String method, Object[] args) { try {
List m = cache.get(method);
if (m == null) return null;
int n = m.size();
for (int i = 0; i < n; i++) {
Method me = m.get(i);
if (isStaticMethod(me) && call_checkArgs(me, args, false))
return me;
}
return null;
} catch (Exception __e) { throw rethrow(__e); } }
//Cl allMethods() { ret allValues(cache); }
}
static class Matches {
String[] m;
Matches() {}
Matches(String... m) {
this.m = m;}
String get(int i) { return i < m.length ? m[i] : null; }
String unq(int i) { return unquote(get(i)); }
String tlc(int i) { return unq(i).toLowerCase(); }
boolean bool(int i) { return "true".equals(unq(i)); }
String rest() { return m[m.length-1]; } // for matchStart
int psi(int i) { return Integer.parseInt(unq(i)); }
public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; }
public int hashCode() { return _hashCode(toList(m)); }
public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); }
}
// for the version with MasterSymbol (used WAY back in "Smart Bot"!) see #1010608
static class Symbol implements CharSequence {
String text;
Symbol() {}
Symbol(String text, boolean dummy) {
this.text = text;} // weird signature to prevent accidental calling
public int hashCode() { return _hashCode(text); }
public String toString() { return text; }
public boolean equals(Object o) {
return this == o;
}
// implementation of CharSequence methods
public int length() { return text.length(); }
public char charAt(int index) { return text.charAt(index); }
public CharSequence subSequence(int start, int end) {
return text.substring(start, end);
}
}
static class Var implements IVar , ISetter {
Var() {}
Var(A v) {
this.v = v;}
A v; // you can access this directly if you use one thread
public synchronized void set(A a) {
if (v != a) {
v = a;
notifyAll();
}
}
public synchronized A get() { return v; }
public synchronized boolean has() { return v != null; }
public void clear() { set(null); }
public synchronized A getAndSet(A a) {
var value = v;
set(a);
return value;
}
public IF0 getter() { return () -> get(); }
public IVF1 setter() { return __50 -> set(__50); }
public String toString() { return str(this.get()); }
}
static class Scorer {
double score, total;
List successes, errors; // set to non-null if you want them filled
boolean verboseFailures, verboseAll;
final void add(double score){ addZeroToOne(score); }
void addZeroToOne(double score) {
++total;
this.score += clamp(score, 0, 1);
}
void addZeroToOneError(double error) {
addZeroToOne(1-error);
}
void addError() { add(false); }
void addError(A info) { add(false, info); }
void error(A info) { addError(info); }
void addOK() { add(true); }
void addOK(A info) { add(true, info); }
void ok() { addOK(); }
void ok(A info) { addOK(info); }
boolean add(boolean correct) {
++total;
if (correct) ++score;
return correct;
}
boolean add(boolean correct, A info) {
main.add(correct ? successes : errors, info);
if (verboseAll || verboseFailures && !correct)
_print((correct ? "[GOOD] " : "[BAD] ") + info);
return add(correct);
}
// works if you use Scorer or Scorer
void eq(Object a, Object b) {
if (_eq(a, b))
add(true);
else
add(false, (A) (a + " != " + b));
}
void print() {
main.print(toString());
}
public String toString() {
return formatDouble(ratioToPercent(score, total), 1) + "% correct (n=" + formatDouble(total, 1) + ")";
}
double get() {
return ratioToPercent(score, total);
}
double percentScore() { return get(); }
double score() { return get(); }
boolean allCorrect() {
return score == total;
}
void add(Scorer scorer) {
if (scorer == null) return;
total += scorer.total;
score += scorer.score;
addAll(successes, scorer.successes);
addAll(errors, scorer.errors);
}
void collectErrors() {
errors = new ArrayList();
}
void collectSuccesses() {
successes = new ArrayList();
}
}
// In the newest pinging system (with flag PingV3), a ping source
// is the object that "allows" some code to run.
// When that code calls ping(), the ping source's action (if defined)
// is triggered.
// This allows randomly interrupting code execution, for example.
static class PingSource {
// returns true if it slept
final public PingSource setAction(IF0 action){ return action(action); }
public PingSource action(IF0 action) { this.action = action; return this; } final public IF0 getAction(){ return action(); }
public IF0 action() { return action; }
volatile IF0 action;
// optional description of this ping source
String text;
// optional thread pool that this ping source likes to run in
ThreadPool threadPool;
PingSource() {}
PingSource(ThreadPool threadPool) {
this.threadPool = threadPool;}
PingSource(ThreadPool threadPool, String text) {
this.text = text;
this.threadPool = threadPool;}
PingSource(IF0 action) {
this.action = action;}
// returns true if it slept
final boolean get() {
var a = action;
return a != null && a.get();
}
final void ping() {
var a = action;
if (a != null) a.get();
}
void cancel() {
action = new Cancelled();
}
class Cancelled implements IF0 {
public Boolean get() { throw new PingSourceCancelledException(PingSource.this); }
}
class Encapsulated implements Runnable , IFieldsToList{
Runnable r;
Encapsulated() {}
Encapsulated(Runnable r) {
this.r = r;}public Object[] _fieldsToList() { return new Object[] {r}; }
public void run() { try {
//System.out.println("Encapsulated running: " + r);
try {
pingSource_tl().set(PingSource.this);
//System.out.println("Ping source set");
ping();
r.run();
//System.out.println("Done running");
} finally {
//System.out.println("Finally");
pingSource_tl().set(null);
}
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return PingSource.this + ": " + r; }
}
void dO(Runnable r) {
if (r == null) return;
threadPool.acquireThreadOrQueue(new Encapsulated(r));
}
public String toString() { String t = text; return nempty(t) ? t : super.toString(); }
ISleeper_v2 sleeper() { return threadPool.sleeper(); }
}
// records its full size (total value count) in a field now
static class MultiMap implements IMultiMap {
Map > data = new HashMap >();
int fullSize;
MultiMap() {}
MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); }
MultiMap(MultiMap map) { putAll(map); }
MultiMap(Map > data) {
this.data = data;}
void put(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
list.add(value);
++fullSize;
}}
void add(A key, B value) { put(key, value); }
void addAll(A key, Collection values) { putAll(key, values); }
void addAllIfNotThere(A key, Collection values) { synchronized(data) {
for (B value : values)
setPut(key, value);
}}
void setPut(A key, B value) { synchronized(data) {
if (!containsPair(key, value))
put(key, value);
}}
boolean containsPair(A key, B value) { synchronized(data) {
return get(key).contains(value);
}}
void putAll(Collection keys, B value) { synchronized(data) {
for (A key : unnullForIteration(keys))
put(key, value);
}}
void putAll(A key, Collection values) { synchronized(data) {
if (nempty(values)) getActual(key).addAll(values);
}}
void putAll(Iterable> pairs) { synchronized(data) {
for (Pair p : unnullForIteration(pairs))
put(p.a, p.b);
}}
void removeAll(A key, Collection values) { synchronized(data) {
for (B value : values)
remove(key, value);
}}
public List get(A key) { synchronized(data) {
List list = data.get(key);
return list == null ? Collections. emptyList() : list;
}}
List getOpt(A key) { synchronized(data) {
return data.get(key);
}}
List getAndClear(A key) { synchronized(data) {
List l = cloneList(data.get(key));
remove(key);
return l;
}}
// returns actual mutable live list
// creates the list if not there
List getActual(A key) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
return list;
}}
void clean(A key) { synchronized(data) {
List list = data.get(key);
if (list != null && list.isEmpty()) {
fullSize -= l(list);
data.remove(key);
}
}}
final public Set keys(){ return keySet(); }
public Set keySet() { synchronized(data) {
return data.keySet();
}}
void remove(A key) { synchronized(data) {
fullSize -= l(this.getOpt(key));
data.remove(key);
}}
final void remove(Pair p){ removePair(p); }
void removePair(Pair p) {
if (p != null) remove(p.a, p.b);
}
void remove(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list != null) {
if (list.remove(value))
fullSize--;
if (list.isEmpty())
data.remove(key);
}
}}
void clear() { synchronized(data) {
data.clear();
}}
boolean containsKey(A key) { synchronized(data) {
return data.containsKey(key);
}}
B getFirst(A key) { synchronized(data) {
List list = get(key);
return list.isEmpty() ? null : list.get(0);
}}
void addAll(MultiMap map) { putAll(map); }
void putAll(MultiMap map) { synchronized(data) {
for (A key : map.keySet())
putAll(key, map.get(key));
}}
void putAll(Map map) { synchronized(data) {
if (map != null) for (Map.Entry e : map.entrySet())
put(e.getKey(), e.getValue());
}}
final public int keyCount(){ return keysSize(); }
public int keysSize() { synchronized(data) { return l(data); }}
final public int fullSize(){ return size(); }
public int size() { synchronized(data) {
return fullSize;
}}
// expensive operation
List reverseGet(B b) { synchronized(data) {
List l = new ArrayList();
for (A key : data.keySet())
if (data.get(key).contains(b))
l.add(key);
return l;
}}
Map > asMap() { synchronized(data) {
return cloneMap(data);
}}
public boolean isEmpty() { synchronized(data) { return data.isEmpty(); }}
// override in subclasses
List _makeEmptyList() {
return new ArrayList();
}
// returns live lists
Collection> allLists() {
synchronized(data) {
return new ArrayList(data.values());
}
}
Collection> values() { return allLists(); }
List allValues() {
return concatLists(data.values());
}
Object mutex() { return data; }
public String toString() { return "mm" + str(data); }
Map> innerMap() { return data; }
}
static class TradingPosition {
final public TradingPosition setCoin(String coin){ return coin(coin); }
public TradingPosition coin(String coin) { this.coin = coin; return this; } final public String getCoin(){ return coin(); }
public String coin() { return coin; }
String coin;
final public TradingPosition setIsLong(boolean isLong){ return isLong(isLong); }
public TradingPosition isLong(boolean isLong) { this.isLong = isLong; return this; } final public boolean getIsLong(){ return isLong(); }
public boolean isLong() { return isLong; }
boolean isLong = false;
final public TradingPosition setLeverage(int leverage){ return leverage(leverage); }
public TradingPosition leverage(int leverage) { this.leverage = leverage; return this; } final public int getLeverage(){ return leverage(); }
public int leverage() { return leverage; }
int leverage;
// How much we originally invest in USDT
final public TradingPosition setMarginInvestment(double marginInvestment){ return marginInvestment(marginInvestment); }
public TradingPosition marginInvestment(double marginInvestment) { this.marginInvestment = marginInvestment; return this; } final public double getMarginInvestment(){ return marginInvestment(); }
public double marginInvestment() { return marginInvestment; }
double marginInvestment;
// How much USDT margin we end up with
final public TradingPosition setMargin(double margin){ return margin(margin); }
public TradingPosition margin(double margin) { this.margin = margin; return this; } final public double getMargin(){ return margin(); }
public double margin() { return margin; }
double margin;
// How much crypto we bet on
final public TradingPosition setAmount(double amount){ return amount(amount); }
public TradingPosition amount(double amount) { this.amount = amount; return this; } final public double getAmount(){ return amount(); }
public double amount() { return amount; }
double amount;
// Is position still open?
final public TradingPosition setOngoing(boolean ongoing){ return ongoing(ongoing); }
public TradingPosition ongoing(boolean ongoing) { this.ongoing = ongoing; return this; } final public boolean getOngoing(){ return ongoing(); }
public boolean ongoing() { return ongoing; }
boolean ongoing = false;
final public TradingPosition setOpeningTime(long openingTime){ return openingTime(openingTime); }
public TradingPosition openingTime(long openingTime) { this.openingTime = openingTime; return this; } final public long getOpeningTime(){ return openingTime(); }
public long openingTime() { return openingTime; }
long openingTime;
final public TradingPosition setClosingTime(long closingTime){ return closingTime(closingTime); }
public TradingPosition closingTime(long closingTime) { this.closingTime = closingTime; return this; } final public long getClosingTime(){ return closingTime(); }
public long closingTime() { return closingTime; }
long closingTime;
final public TradingPosition setOpeningPrice(double openingPrice){ return openingPrice(openingPrice); }
public TradingPosition openingPrice(double openingPrice) { this.openingPrice = openingPrice; return this; } final public double getOpeningPrice(){ return openingPrice(); }
public double openingPrice() { return openingPrice; }
double openingPrice;
// closing or current price
final public TradingPosition setClosingPrice(double closingPrice){ return closingPrice(closingPrice); }
public TradingPosition closingPrice(double closingPrice) { this.closingPrice = closingPrice; return this; } final public double getClosingPrice(){ return closingPrice(); }
public double closingPrice() { return closingPrice; }
double closingPrice;
final public TradingPosition setOpeningFees(double openingFees){ return openingFees(openingFees); }
public TradingPosition openingFees(double openingFees) { this.openingFees = openingFees; return this; } final public double getOpeningFees(){ return openingFees(); }
public double openingFees() { return openingFees; }
double openingFees;
final public TradingPosition setClosingFees(double closingFees){ return closingFees(closingFees); }
public TradingPosition closingFees(double closingFees) { this.closingFees = closingFees; return this; } final public double getClosingFees(){ return closingFees(); }
public double closingFees() { return closingFees; }
double closingFees;
final public TradingPosition setProfit(double profit){ return profit(profit); }
public TradingPosition profit(double profit) { this.profit = profit; return this; } final public double getProfit(){ return profit(); }
public double profit() { return profit; }
double profit = Double.NaN;
// Actual price movement during position
final public TradingPosition setCandle(TradingCandle candle){ return candle(candle); }
public TradingPosition candle(TradingCandle candle) { this.candle = candle; return this; } final public TradingCandle getCandle(){ return candle(); }
public TradingCandle candle() { return candle; }
TradingCandle candle;
// Signal we acted on (optional)
final public TradingPosition setAfterSignal(TradingSignal afterSignal){ return afterSignal(afterSignal); }
public TradingPosition afterSignal(TradingSignal afterSignal) { this.afterSignal = afterSignal; return this; } final public TradingSignal getAfterSignal(){ return afterSignal(); }
public TradingSignal afterSignal() { return afterSignal; }
TradingSignal afterSignal;
double openingFeePercentage() {
return doubleRatio(openingFees, margin*leverage);
}
double priceDifference() {
return closingPrice-openingPrice;
}
double leveragedPriceDifference() {
return priceDifference()*leverage;
}
// PNL = Profit & Loss
final double relativeValue(){ return expectedPNL(); }
double expectedPNL() {
return !isNaN(profit) ? profit : (isLong() ? 1 : -1)*leveragedPriceDifference()*amount;
}
boolean isWinner() { return relativeValue() >= 0; }
boolean isOpen() { return ongoing; }
int direction() { return isLong() ? 1 : -1; }
static TradingPosition fromStrategy(G22TradingStrategy.Position p) {
return new TradingPosition()
.profit(p.profit())
.openingTime(p.openingTime())
.closingTime(p.closingTime())
.openingPrice(p.openingPrice())
.closingPrice(p.closingPrice())
.isLong(p.direction > 0)
.leverage(iround(p.leverage));
}
}
// Note: This does have the values problem (complicated values can cause memory leaks)
static class BetterThreadLocal {
Map map = newWeakHashMap();
BetterThreadLocal() {}
BetterThreadLocal(A value) { set(value); }
boolean isSet() { return map.containsKey(currentThread()); }
A get() {
if (map.containsKey(currentThread()))
return map.get(currentThread());
A value = initialValue();
set(value);
return value;
}
A get(Thread thread) {
return thread == null ? null : map.get(thread);
}
void set(A a) {
map.put(currentThread(), a);
}
public A initialValue() { return null; }
}
interface IntSize {
int size();
default boolean isEmpty() { return size() == 0; }
}
/*
* @(#)WeakHashMap.java 1.5 98/09/30
*
* Copyright 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
// From https://github.com/mernst/plume-lib/blob/df0bfafc3c16848d88f4ea0ef3c8bf3367ae085e/java/src/plume/WeakHasherMap.java
static final class WeakHasherMap extends AbstractMap implements Map {
private Hasher hasher = null;
/*@Pure*/
private boolean keyEquals(Object k1, Object k2) {
return (hasher==null ? k1.equals(k2)
: hasher.equals(k1, k2));
}
/*@Pure*/
private int keyHashCode(Object k1) {
return (hasher==null ? k1.hashCode()
: hasher.hashCode(k1));
}
// The WeakKey class can't be static because it depends on the hasher.
// That in turn means that its methods can't be static.
// However, I need to be able to call the methods such as create() that
// were static in the original version of this code.
// This finesses that.
private /*@Nullable*/ WeakKey WeakKeyCreate(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private /*@Nullable*/ WeakKey WeakKeyCreate(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
// Cannot be a static class: uses keyHashCode() and keyEquals()
private final class WeakKey extends WeakReference {
private int hash; /* Hashcode of key, stored here since the key
may be tossed by the GC */
private WeakKey(K k) {
super(k);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private WeakKey(K k, ReferenceQueue super K> q) {
super(k, q);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
/* A WeakKey is equal to another WeakKey iff they both refer to objects
that are, in turn, equal according to their own equals methods */
/*@Pure*/
@Override
public boolean equals(/*@Nullable*/ Object o) {
if (o == null) return false; // never happens
if (this == o) return true;
// This test is illegal because WeakKey is a generic type,
// so use the getClass hack below instead.
// if (!(o instanceof WeakKey)) return false;
if (!(o.getClass().equals(WeakKey.class))) return false;
Object t = this.get();
@SuppressWarnings("unchecked")
Object u = ((WeakKey)o).get();
if ((t == null) || (u == null)) return false;
if (t == u) return true;
return keyEquals(t, u);
}
/*@Pure*/
@Override
public int hashCode() {
return hash;
}
}
/* Hash table mapping WeakKeys to values */
private HashMap hash;
/* Reference queue for cleared WeakKeys */
private ReferenceQueue super K> queue = new ReferenceQueue();
/* Remove all invalidated entries from the map, that is, remove all entries
whose keys have been discarded. This method should be invoked once by
each public mutator in this class. We don't invoke this method in
public accessors because that can lead to surprising
ConcurrentModificationExceptions. */
@SuppressWarnings("unchecked")
private void processQueue() {
WeakKey wk;
while ((wk = (WeakKey)queue.poll()) != null) { // unchecked cast
hash.remove(wk);
}
}
/* -- Constructors -- */
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the given load factor.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @param loadFactor the load factor of the WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero, or if the load factor is
* nonpositive
*/
public WeakHasherMap(int initialCapacity, float loadFactor) {
hash = new HashMap(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the default load factor, which is
* 0.75.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero
*/
public WeakHasherMap(int initialCapacity) {
hash = new HashMap(initialCapacity);
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
*/
public WeakHasherMap() {
hash = new HashMap();
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
* The WeakHashMap uses the specified hasher for hashing
* keys and comparing them for equality.
* @param h the Hasher to use when hashing values for this map
*/
public WeakHasherMap(Hasher h) {
hash = new HashMap();
hasher = h;
}
/* -- Simple queries -- */
/**
* Returns the number of key-value mappings in this map.
* Note: In contrast to most implementations of the
* Map interface, the time required by this operation is
* linear in the size of the map.
*/
/*@Pure*/
@Override
public int size() {
return entrySet().size();
}
/**
* Returns true if this map contains no key-value mappings.
*/
/*@Pure*/
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
/**
* Returns true if this map contains a mapping for the
* specified key.
*
* @param key the key whose presence in this map is to be tested
*/
/*@Pure*/
@Override
public boolean containsKey(Object key) {
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.containsKey(WeakKeyCreate(kkey));
}
/* -- Lookup and modification operations -- */
/**
* Returns the value to which this map maps the specified key.
* If this map does not contain a value for this key, then return
* null.
*
* @param key the key whose associated value, if any, is to be returned
*/
/*@Pure*/
@Override
public /*@Nullable*/ V get(Object key) { // type of argument is Object, not K
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.get(WeakKeyCreate(kkey));
}
/**
* Updates this map so that the given key maps to the given
* value. If the map previously contained a mapping for
* key then that mapping is replaced and the previous value is
* returned.
*
* @param key the key that is to be mapped to the given
* value
* @param value the value to which the given key is to be
* mapped
*
* @return the previous value to which this key was mapped, or
* null if if there was no mapping for the key
*/
@Override
public V put(K key, V value) {
processQueue();
return hash.put(WeakKeyCreate(key, queue), value);
}
/**
* Removes the mapping for the given key from this map, if
* present.
*
* @param key the key whose mapping is to be removed
*
* @return the value to which this key was mapped, or null if
* there was no mapping for the key
*/
@Override
public V remove(Object key) { // type of argument is Object, not K
processQueue();
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.remove(WeakKeyCreate(kkey));
}
/**
* Removes all mappings from this map.
*/
@Override
public void clear() {
processQueue();
hash.clear();
}
/* -- Views -- */
/* Internal class for entries */
// This can't be static, again because of dependence on hasher.
@SuppressWarnings("TypeParameterShadowing")
private final class Entry implements Map.Entry {
private Map.Entry ent;
private K key; /* Strong reference to key, so that the GC
will leave it alone as long as this Entry
exists */
Entry(Map.Entry ent, K key) {
this.ent = ent;
this.key = key;
}
/*@Pure*/
@Override
public K getKey() {
return key;
}
/*@Pure*/
@Override
public V getValue() {
return ent.getValue();
}
@Override
public V setValue(V value) {
return ent.setValue(value);
}
/*@Pure*/
private boolean keyvalEquals(K o1, K o2) {
return (o1 == null) ? (o2 == null) : keyEquals(o1, o2);
}
/*@Pure*/
private boolean valEquals(V o1, V o2) {
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
/*@Pure*/
@SuppressWarnings("NonOverridingEquals")
public boolean equals(Map.Entry e /* Object o*/) {
// if (! (o instanceof Map.Entry)) return false;
// Map.Entry e = (Map.Entry)o;
return (keyvalEquals(key, e.getKey())
&& valEquals(getValue(), e.getValue()));
}
/*@Pure*/
@Override
public int hashCode() {
V v;
return (((key == null) ? 0 : keyHashCode(key))
^ (((v = getValue()) == null) ? 0 : v.hashCode()));
}
}
/* Internal class for entry sets */
private final class EntrySet extends AbstractSet> {
Set> hashEntrySet = hash.entrySet();
@Override
public Iterator> iterator() {
return new Iterator>() {
Iterator> hashIterator = hashEntrySet.iterator();
Map.Entry next = null;
@Override
public boolean hasNext() {
while (hashIterator.hasNext()) {
Map.Entry ent = hashIterator.next();
WeakKey wk = ent.getKey();
K k = null;
if ((wk != null) && ((k = wk.get()) == null)) {
/* Weak key has been cleared by GC */
continue;
}
next = new Entry(ent, k);
return true;
}
return false;
}
@Override
public Map.Entry next() {
if ((next == null) && !hasNext())
throw new NoSuchElementException();
Map.Entry e = next;
next = null;
return e;
}
@Override
public void remove() {
hashIterator.remove();
}
};
}
/*@Pure*/
@Override
public boolean isEmpty() {
return !(iterator().hasNext());
}
/*@Pure*/
@Override
public int size() {
int j = 0;
for (Iterator> i = iterator(); i.hasNext(); i.next()) j++;
return j;
}
@Override
public boolean remove(Object o) {
processQueue();
if (!(o instanceof Map.Entry,?>)) return false;
@SuppressWarnings("unchecked")
Map.Entry e = (Map.Entry)o; // unchecked cast
Object ev = e.getValue();
WeakKey wk = WeakKeyCreate(e.getKey());
Object hv = hash.get(wk);
if ((hv == null)
? ((ev == null) && hash.containsKey(wk)) : hv.equals(ev)) {
hash.remove(wk);
return true;
}
return false;
}
/*@Pure*/
@Override
public int hashCode() {
int h = 0;
for (Iterator> i = hashEntrySet.iterator(); i.hasNext(); ) {
Map.Entry ent = i.next();
WeakKey wk = ent.getKey();
Object v;
if (wk == null) continue;
h += (wk.hashCode()
^ (((v = ent.getValue()) == null) ? 0 : v.hashCode()));
}
return h;
}
}
private /*@Nullable*/ Set> entrySet = null;
/**
* Returns a Set view of the mappings in this map.
*/
/*@SideEffectFree*/
@Override
public Set> entrySet() {
if (entrySet == null) entrySet = new EntrySet();
return entrySet;
}
// find matching key
K findKey(Object key) {
processQueue();
K kkey = (K) key;
// TODO: use replacement for HashMap to avoid reflection
WeakKey wkey = WeakKeyCreate(kkey);
WeakKey found = hashMap_findKey(hash, wkey);
return found == null ? null : found.get();
}
}
static class GeometricPriceCells implements PriceCells {
GeometricPriceCells() {}
// cell size in percent
final public GeometricPriceCells setCellSizeInPercent(double cellSizeInPercent){ return cellSizeInPercent(cellSizeInPercent); }
public GeometricPriceCells cellSizeInPercent(double cellSizeInPercent) { this.cellSizeInPercent = cellSizeInPercent; return this; } final public double getCellSizeInPercent(){ return cellSizeInPercent(); }
public double cellSizeInPercent() { return cellSizeInPercent; }
double cellSizeInPercent;
// one of the cell limits
final public GeometricPriceCells setBasePrice(double basePrice){ return basePrice(basePrice); }
public GeometricPriceCells basePrice(double basePrice) { this.basePrice = basePrice; return this; } final public double getBasePrice(){ return basePrice(); }
public double basePrice() { return basePrice; }
double basePrice = 1000;
GeometricPriceCells(double cellSizeInPercent) {
this.cellSizeInPercent = cellSizeInPercent;}
GeometricPriceCells(double basePrice, double cellSizeInPercent) {
this.cellSizeInPercent = cellSizeInPercent;
this.basePrice = basePrice;}
double ratio() {
return 1+cellSizeInPercent/100;
}
double toLogScale(double price) {
return log(price, ratio());
}
double fromLogScale(double logPrice) {
return pow(ratio(), logPrice);
}
double logBasePrice() {
return toLogScale(basePrice);
}
double remainder(double price) {
return remainder(toLogScale(price));
}
double remainderLog(double logPrice) {
return frac(logPrice-logBasePrice());
}
// TODO: fix this logic's rounding problems
public boolean isCellLimit(double price) {
return remainder(price) == 0;
}
public double nextCellLimitLog(double logPrice) {
double r = remainderLog(logPrice);
return logPrice + 1-r;
}
public double nextCellLimit(double price) {
return fromLogScale(nextCellLimitLog(toLogScale(price)));
}
public double previousCellLimitLog(double logPrice) {
double r = remainderLog(logPrice);
return logPrice - (r == 0 ? 1 : r);
}
public double previousCellLimit(double price) {
return fromLogScale(previousCellLimitLog(toLogScale(price)));
}
public double nCellLimitsDown(double price, int n) {
double logPrice = toLogScale(price);
logPrice = previousCellLimitLog(logPrice)-(n-1);
return fromLogScale(logPrice);
}
public double nCellLimitsUp(double price, int n) {
double logPrice = toLogScale(price);
logPrice = nextCellLimitLog(logPrice)+n;
return fromLogScale(logPrice);
}
public double priceToCellNumber(double price) {
return toLogScale(price)-logBasePrice();
}
public double cellNumberToPrice(double cellNumber) {
return fromLogScale(cellNumber+logBasePrice());
}
public String toString() {
return formatDouble2(cellSizeInPercent) + "% cells with C0=" + formatPrice(basePrice);
}
}
// -has fast nextElement() and prevElement()
// -design allows for more functions like reordering the list
// -Saves up to 34% in space over LinkedHashSet
// (e.g. 22% for a set of 1,000 Ints)
static class CompactLinkedHashSet extends AbstractSet {
UnsynchronizedCompactHashSet> entries = new UnsynchronizedCompactHashSet();
Entry head, tail;
static class Entry {
A value;
Entry prev, next;
public int hashCode() {
return _hashCode(value);
}
// "magic" equals function for CompactHashSet lookup without temp object
public boolean equals(Object o) {
return o == this || eq(value, o);
}
}
public boolean add(A a) {
if (entries.contains(a)) return false;
Entry n = new Entry();
n.value = a;
n.prev = tail;
if (tail != null) tail.next = n;
tail = n;
if (head == null) head = n;
entries.add(n);
return true;
}
public boolean remove(Object a) {
return remove(entries.find(a));
}
public boolean remove(Entry node) {
if (node == null) return false;
if (node.next != null) node.next.prev = node.prev; else tail = node.prev;
if (node.prev != null) node.prev.next = node.next; else head = node.next;
entries.remove(node);
return true;
}
public int size() { return entries.size(); }
public IterableIterator iterator() {
return new IterableIterator () {
Entry entry = head, prev = null;
public boolean hasNext() { return entry != null; }
public A next() {
A a = entry.value;
prev = entry;
entry = entry.next;
return a;
}
// untested
public void remove() {
if (prev == null) throw new IllegalStateException();
CompactLinkedHashSet.this.remove(prev);
prev = null;
}
};
}
public void clear() {
entries.clear();
head = tail = null;
}
public boolean contains(Object a) {
return entries.contains(a);
}
public A find(Object o) {
Entry e = entries.find(o);
return e == null ? null : e.value;
}
public A prevElement(A a) {
Entry e = entries.find(a);
if (e == null || e.prev == null) return null;
return e.prev.value;
}
public A nextElement(A a) {
Entry e = entries.find(a);
if (e == null || e.next == null) return null;
return e.next.value;
}
public A first() { return head == null ? null : head.value; }
public A last() { return tail == null ? null : tail.value; }
boolean removeIfSame(Object o) {
A value = find(o);
if (value == o) {
remove(value);
return true;
}
return false;
}
}
interface G2Drawable {
void drawOn(Graphics2D g);
default void drawOn(BufferedImage img) {
drawOn(img.createGraphics());
}
}
static class ScaledDiagram {
final public ScaledDiagram setW(int w){ return w(w); }
public ScaledDiagram w(int w) { this.w = w; return this; } final public int getW(){ return w(); }
public int w() { return w; }
int w = 600;
final public ScaledDiagram setH(int h){ return h(h); }
public ScaledDiagram h(int h) { this.h = h; return this; } final public int getH(){ return h(); }
public int h() { return h; }
int h = 400;
final public ScaledDiagram setHorizontalMargin(int horizontalMargin){ return horizontalMargin(horizontalMargin); }
public ScaledDiagram horizontalMargin(int horizontalMargin) { this.horizontalMargin = horizontalMargin; return this; } final public int getHorizontalMargin(){ return horizontalMargin(); }
public int horizontalMargin() { return horizontalMargin; }
int horizontalMargin = 10;
final public ScaledDiagram setVerticalMargin(int verticalMargin){ return verticalMargin(verticalMargin); }
public ScaledDiagram verticalMargin(int verticalMargin) { this.verticalMargin = verticalMargin; return this; } final public int getVerticalMargin(){ return verticalMargin(); }
public int verticalMargin() { return verticalMargin; }
int verticalMargin = 10;
final public ScaledDiagram setHorizontalRange(DoubleRange horizontalRange){ return horizontalRange(horizontalRange); }
public ScaledDiagram horizontalRange(DoubleRange horizontalRange) { this.horizontalRange = horizontalRange; return this; } final public DoubleRange getHorizontalRange(){ return horizontalRange(); }
public DoubleRange horizontalRange() { return horizontalRange; }
DoubleRange horizontalRange;
final public ScaledDiagram setVerticalRange(DoubleRange verticalRange){ return verticalRange(verticalRange); }
public ScaledDiagram verticalRange(DoubleRange verticalRange) { this.verticalRange = verticalRange; return this; } final public DoubleRange getVerticalRange(){ return verticalRange(); }
public DoubleRange verticalRange() { return verticalRange; }
DoubleRange verticalRange;
// Ranges in pixels that we can paint in (image size minus margins)
DoubleRange xRange() { return doubleRange(horizontalMargin, w-horizontalMargin); }
DoubleRange yRange() { return doubleRange(h-verticalMargin, verticalMargin); }
double xToScreen(double x) { return transformBetweenDoubleRanges(x, horizontalRange(), xRange()); }
double yToScreen(double y) { return transformBetweenDoubleRanges(y, verticalRange(), yRange()); }
int xToScreen_int(double x) { return iround(xToScreen(x)); }
int yToScreen_int(double y) { return iround(yToScreen(y)); }
double xFromScreen(double x) { return transformBetweenDoubleRanges(x, xRange(), horizontalRange()); }
double yFromScreen(double y) { return transformBetweenDoubleRanges(y, yRange(), verticalRange()); }
public int getWidth() { return w; }
public int getHeight() { return h; }
boolean hasScale() { return horizontalRange != null && verticalRange != null; }
}
static class Pair implements Comparable> {
final public Pair setA(A a){ return a(a); }
public Pair a(A a) { this.a = a; return this; } final public A getA(){ return a(); }
public A a() { return a; }
A a;
final public Pair setB(B b){ return b(b); }
public Pair b(B b) { this.b = b; return this; } final public B getB(){ return b(); }
public B b() { return b; }
B b;
Pair() {}
Pair(A a, B b) {
this.b = b;
this.a = a;}
public int hashCode() {
return hashCodeFor(a) + 2*hashCodeFor(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);
}
public String toString() {
return "<" + a + ", " + b + ">";
}
public int compareTo(Pair p) {
if (p == null) return 1;
int i = ((Comparable ) a).compareTo(p.a);
if (i != 0) return i;
return ((Comparable) b).compareTo(p.b);
}
}
static class Fail extends RuntimeException implements IFieldsToList{
Object[] objects;
Fail() {}
Fail(Object... objects) {
this.objects = objects;}public Object[] _fieldsToList() { return new Object[] {objects}; }
Fail(Throwable cause, Object... objects) {
super(cause);
this.objects = objects;
}
public String toString() { return joinNemptiesWithColon("Fail", getMessage()); }
public String getMessage() { return commaCombine(getCause(), objects); }
}
interface PriceCells {
boolean isCellLimit(double price);
// next-higher cell limit or NaN if no more cells
double nextCellLimit(double price);
// next-lower cell limit or NaN if no more cells
double previousCellLimit(double price);
// go n steps down
double nCellLimitsDown(double price, int n);
// go n steps up
double nCellLimitsUp(double price, int n);
// convert to "cell space" (0=first cell limit, 1=next cell limit, -1=previous cell limit etc)
default double toCellNumber(double price){ return priceToCellNumber(price); }
double priceToCellNumber(double price);
default double fromCellNumber(double cellNumber){ return cellNumberToPrice(cellNumber); }
double cellNumberToPrice(double cellNumber);
default double basePrice() { return cellNumberToPrice(0); }
}
static class Rect implements WidthAndHeight , IFieldsToList{
static final String _fieldOrder = "x y w h";
int x;
int y;
int w;
int h;
Rect() {}
Rect(int x, int y, int w, int h) {
this.h = h;
this.w = w;
this.y = y;
this.x = x;}
public boolean equals(Object o) {
if (!(o instanceof Rect)) return false;
Rect __1 = (Rect) o;
return x == __1.x && y == __1.y && w == __1.w && h == __1.h;
}
public int hashCode() {
int h = 2543108;
h = boostHashCombine(h, _hashCode(x));
h = boostHashCombine(h, _hashCode(y));
h = boostHashCombine(h, _hashCode(w));
h = boostHashCombine(h, _hashCode(h));
return h;
}
public Object[] _fieldsToList() { return new Object[] {x, y, w, h}; }
Rect(Rectangle r) {
x = r.x;
y = r.y;
w = r.width;
h = r.height;
}
Rect(Pt p, int w, int h) {
this.h = h;
this.w = w; x = p.x; y = p.y; }
Rect(Rect r) { x = r.x; y = r.y; w = r.w; h = r.h; }
final Rectangle getRectangle() {
return new Rectangle(x, y, w, h);
}
public String toString() {
return x + "," + y + " / " + w + "," + h;
}
final int x1() { return x; }
final int y1() { return y; }
final int x2() { return x + w; }
final int y2() { return y + h; }
final boolean contains(Pt p) {
return contains(p.x, p.y);
}
final boolean contains(int _x, int _y) {
return _x >= x && _y >= y && _x < x+w && _y < y+h;
}
final boolean contains(Rectangle r) {
return rectContains(this, r);
}
final boolean empty() { return w <= 0 || h <= 0; }
final public int getWidth() { return w; }
final public int getHeight() { return h; }
final public int area() { return w*h; }
final public int x() { return x; }
final public int y() { return y; }
WidthAndHeight widthAndHeight() { return main.widthAndHeight(w, h); }
}
static class Pt implements Comparable, IDoublePt {
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 o instanceof Pt && x == ((Pt) o).x && y == ((Pt) o).y;
}
public int hashCode() {
return boostHashCombine(x, y);
}
// compare in scan order
public int compareTo(Pt p) {
if (y != p.y) return cmp(y, p.y);
return cmp(x, p.x);
}
public String toString() {
return x + ", " + y;
}
double length() { return sqrt(x*x+y*y); }
public Pt minus(Pt p) { return ptMinus(this, p); }
public double x_double() { return x; }
public double y_double() { return y; }
}
static class BufferedImageWithMeta extends BufferedImage implements IMeta {
BufferedImageWithMeta(ColorModel cm,
WritableRaster raster,
boolean isRasterPremultiplied,
Hashtable,?> properties) {
super(cm, raster, isRasterPremultiplied, properties);
}
// Meta - a "minimal" approach to adding meta-level to Java objects
// (implementing the interface IMeta)
// We allocate one extra field for each Java object to make it
// reasoning-compatible (reasoning-compatible = extensible with
// fields of any name at runtime).
//
// We couldn't go for 0 extra fields (meta values must be linked
// directly from the object) and there are no half fields in
// Java... so there you go.
//
// Also, if you don't use any meta data, you are probably not
// reasoning about anything. The point of reasoning in JavaX is
// to attach information to objects directly used in the program.
// Possible information contained in the meta field:
// Origin, destination, security level, sender, cost center,
// purpose, list of reifications, ...
// So here it is. THE FIELD YOU HAVE BEEN WAITING FOR!
// [We also have IMeta to retrofit foreign classes (rare but
// probably useful).]
//////////////////////
// The "meta" field //
//////////////////////
// Generic meta value of any kind, but the typical case is it's a
// Map with extra field values for the object etc.
// "meta" is volatile to avoid synchronization; but you can also synchronize on
// _tempMetaMutex() which is usually the object itself. Collections
// and maps are exempt from using the collections's monitor as the meta
// mutex because their monitor tends to be held for long operations
// (e.g. cloneList). For those we use a substantially more complex
// algorithm using a weakMap. Probably overkill. I may reconsider.
volatile Object meta;
// The meta field is not transient, thus by default it will be
// persisted like anything else unless you customize your object
// to suppress or modulate this.
// ...and the interface methods
public void _setMeta(Object meta) { this.meta = meta; }
public Object _getMeta() { return meta; }
// MOST functions are implemented in IMeta (default implementations)
// Scaffolding convenience functions
final boolean scaffolding(){ return scaffoldingEnabled(); }
final boolean scaffolded(){ return scaffoldingEnabled(); }
boolean scaffoldingEnabled() { return main.scaffoldingEnabled(this); }
boolean scaffoldingEnabled(Object o) { return main.scaffoldingEnabled(o); }
// Implementing setMetaToString
String toString_base() { return super.toString(); }
public String toString() {
Object o = metaGet("toString", this);
if (o instanceof String) return ((String) o);
if (o instanceof IF1) return str(((IF1) o).get(this));
return toString_base();
}
}
// it's unclear whether the end is inclusive or exclusive
// (usually exclusive I guess)
static class IntRange {
int start, end;
IntRange() {}
IntRange(int start, int end) {
this.end = end;
this.start = start;}
IntRange(IntRange r) { start = r.start; end = r.end; }
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
final int length() { return end-start; }
final boolean empty() { return start >= end; }
final boolean isEmpty() { return start >= end; }
static String _fieldOrder = "start end";
public String toString() { return "[" + start + ";" + end + "]"; }
}
static abstract class F0 {
abstract A get();
}
static abstract class F1 {
abstract B get(A a);
}
// 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 interface MakesBufferedImage extends WidthAndHeight {
BufferedImage getBufferedImage();
public default void drawAt(Graphics2D g, int x, int y) {
g.drawImage(getBufferedImage(), x, y, null);
}
default int getWidth() { return getBufferedImage().getWidth(); }
default int getHeight() { return getBufferedImage().getHeight(); }
}
interface PCallPolicy {
void handlePcallFail(Throwable e);
}
final static class DoubleRange implements Comparable {
final public double getStart(){ return start(); }
public double start() { return start; }
double start;
final public double getEnd(){ return end(); }
public double end() { return end; }
double end;
DoubleRange() {}
DoubleRange(double start, double end) {
this.end = end;
this.start = start;}
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
double length() { return end-start; }
boolean isEmpty() { return start >= end; }
double center() { return (start+end)/2; }
static String _fieldOrder = "start end";
public String toString() { return "[" + start + ";" + end + "]"; }
@Override public int compareTo(DoubleRange r) {
int c = cmp(start, r.start);
if (c != 0) return c;
return cmp(end, r.end);
}
boolean contains(double d) {
return d >= start && d <= end;
}
}
public static interface IF0 {
A get();
}
static interface Hasher {
int hashCode(A a);
boolean equals(A a, A b);
}
static interface IF2 {
C get(A a, B b);
}
static interface IF1 {
B get(A a);
}
static class DoublePt implements IDoublePt {
double x, y;
DoublePt() {}
DoublePt(Point p) {
x = p.x;
y = p.y;
}
DoublePt(double x, double y) {
this.y = y;
this.x = x;}
public boolean equals(Object p) { if (p instanceof DoublePt) { return x == ((DoublePt) p).x && y == ((DoublePt) p).y; } return false; }
public int hashCode() {
return boostHashCombine(main.hashCode(x), main.hashCode(y));
}
public String toString() {
return x + ", " + y;
}
double length() { return sqrt(x*x+y*y); }
public double x_double() { return x; }
public double y_double() { return y; }
}
// TODO: subclass RuntimeException and use Meta instead of DynamicObject
static class PersistableThrowable extends DynamicObject {
String className;
String msg;
String stacktrace;
final public PersistableThrowable setActualThrowable(Throwable actualThrowable){ return actualThrowable(actualThrowable); }
public PersistableThrowable actualThrowable(Throwable actualThrowable) { this.actualThrowable = actualThrowable; return this; } final public Throwable getActualThrowable(){ return actualThrowable(); }
public Throwable actualThrowable() { return actualThrowable; }
transient Throwable actualThrowable;
PersistableThrowable() {}
PersistableThrowable(Throwable e) {
actualThrowable = e;
if (e == null)
className = "Crazy Null Error";
else {
className = getClassName(e).replace('/', '.');
msg = e.getMessage();
stacktrace = getStackTrace_noRecord(e);
}
}
public String toString() {
return nempty(msg) ? className + ": " + msg : className;
}
RuntimeException asRuntimeException() {
if (actualThrowable != null)
return main.asRuntimeException(actualThrowable);
return new Fail(this);
}
}
static interface IVF1 {
void get(A a);
}
static interface IVF2 {
void get(A a, B b);
}
interface IDoublePt {
public double x_double();
public double y_double();
}
static interface WidthAndHeight {
default int w(){ return getWidth(); }
default int width(){ return getWidth(); }
int getWidth();
default int h(){ return getHeight(); }
default int height(){ return getHeight(); }
int getHeight();
public default Rect bounds() { return rect(0, 0, getWidth(), getHeight()); }
default int area() { return toInt(areaAsLong()); }
default long areaAsLong() { return longMul(w(), h()); }
}
static class PingSourceCancelledException extends RuntimeException implements IFieldsToList{
PingSource pingSource;
PingSourceCancelledException() {}
PingSourceCancelledException(PingSource pingSource) {
this.pingSource = pingSource;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + pingSource + ")"; }public Object[] _fieldsToList() { return new Object[] {pingSource}; }
}
static class SynchronizedLongBuffer implements ILongBuffer {
long[] data;
int size;
SynchronizedLongBuffer() {}
SynchronizedLongBuffer(int size) { if (size != 0) data = new long[size]; }
SynchronizedLongBuffer(Iterable l) {
if (l instanceof Collection) allocate(((Collection) l).size());
addAll(l);
}
public synchronized 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;
}
synchronized void allocate(int n) {
data = resizeLongArray(data, max(n, size()));
}
public synchronized void addAll(Iterable l) {
if (l != null) for (long i : l) add(i);
}
public synchronized long[] toArray() {
return size == 0 ? null : resizeLongArray(data, size);
}
synchronized List toList() {
return longArrayToList(data, 0, size);
}
public synchronized List asVirtualList() {
return listFromFunction(__57 -> get(__57), size);
}
synchronized void reset() { size = 0; }
void clear() { reset(); }
synchronized public int size() { return size; }
public synchronized boolean isEmpty() { return size == 0; }
public synchronized long get(int idx) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
return data[idx];
}
synchronized void set(int idx, long value) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
data[idx] = value;
}
public synchronized long popLast() {
if (size == 0) throw fail("empty buffer");
return data[--size];
}
public synchronized long last() { return data[size-1]; }
synchronized long nextToLast() { return data[size-2]; }
public String toString() { return squareBracket(joinWithSpace(toList())); }
public synchronized Iterator iterator() {
return new IterableIterator() {
int i = 0;
public boolean hasNext() { return i < size(); }
public Long next() {
synchronized(SynchronizedLongBuffer.this) {
if (!hasNext()) throw fail("Index out of bounds: " + i);
return data[i++];
}
}
};
}
public synchronized void trimToSize() {
data = resizeLongArray(data, size);
}
synchronized 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 synchronized long poll() {
return size == 0 ? -1 : data[--size];
}
public synchronized void insertAt(int idx, long[] l) {
int n = l(l);
if (n == 0) return;
long[] newData = new long[size+n];
arraycopy(data, 0, newData, 0, idx);
arraycopy(l, 0, newData, idx, n);
arraycopy(data, idx, newData, idx+n, size-idx);
data = newData;
size = newData.length;
}
}
static interface IMeta {
// see class "Meta" for the bla bla
public void _setMeta(Object meta);
public Object _getMeta();
default public IAutoCloseableF0 _tempMetaMutex() {
return new IAutoCloseableF0() {
public Object get() { return IMeta.this; }
public void close() {}
};
}
// actually query another object
default public Object getMeta(Object obj, Object key){ return metaGet(obj, key); }
default public Object metaGet(Object obj, Object key) {
// call global function
return metaMapGet(obj, key);
}
default public Object metaGet(String key, Object obj) {
// call global function
return metaMapGet(obj, key);
}
default public Object getMeta(Object key){ return metaGet(key); }
default public Object metaGet(Object key) {
if (key == null) return null;
Object meta = _getMeta();
if (meta instanceof Map) return ((Map) meta).get(key);
return null;
}
default public void metaSet(IMeta obj, Object key, Object value){ metaPut(obj, key, value); }
default public void metaPut(IMeta obj, Object key, Object value) {
// call global function
metaMapPut(obj, key, value);
}
default public void metaSet(Object key, Object value){ metaPut(key, value); }
default public void metaPut(Object key, Object value) {
if (key == null) return;
Map map = convertObjectMetaToMap(this);
syncMapPutOrRemove(map, key, value);
}
}
// The idea is to leave max as the actual number of cores the system
// has (numberOfCores()), and in case of being fully booked, raise an
// alert (customerMustWaitAlert) which can be handled by a strategy
// object (different reactions are possible).
// If nothing is done in such an event, clients are processed serially
// (no guarantees of order), split up among the available threads.
/* SYNChronisation order:
1. PooledThread
2. ThreadPool */
static class ThreadPool implements AutoCloseable {
int max = numberOfCores();
List all = new ArrayList();
Set used = new HashSet();
Set free = new HashSet();
boolean verbose, retired;
// our own ping surce so we can start threads & keep them running
class InternalPingSource extends PingSource {}
InternalPingSource internalPingSource = new InternalPingSource();
MultiSleeper sleeper = new MultiSleeper();
ThreadPool() {}
ThreadPool(int max) {
this.max = max;}
synchronized int maxSize() { return max; }
synchronized int total() { return l(used)+l(free); }
transient Set onCustomerMustWaitAlert;
public ThreadPool onCustomerMustWaitAlert(Runnable r) { onCustomerMustWaitAlert = createOrAddToSyncLinkedHashSet(onCustomerMustWaitAlert, r); return this; }
public ThreadPool removeCustomerMustWaitAlertListener(Runnable r) { main.remove(onCustomerMustWaitAlert, r); return this; }
public void customerMustWaitAlert() { if (onCustomerMustWaitAlert != null) for (var listener : onCustomerMustWaitAlert) pcallF_typed(listener); }
void fireCustomerMustWaitAlert() {
vmBus_send("customerMustWaitAlert", this, currentThread());
customerMustWaitAlert();
}
// DOESN'T WAIT. adds action to a thread's queue if nothing is
// available immediately.
PooledThread acquireThreadOrQueue(Runnable action) {
if (action == null) return null;
PooledThread t;
synchronized(this) {
if (_hasFreeAfterCreating()) {
t = _firstFreeThread();
markUsed(t);
} else
t = _anyThread();
}
t.addWork(action); // will move it from free to used
return t;
}
// run in synchronized block
boolean _hasFreeAfterCreating() {
checkNotRetired();
if (nempty(free)) return true;
if (total() < max) {
PooledThread t = newThread();
all.add(t);
free.add(t);
return true;
}
return false;
}
// WAITS until thread is available
PooledThread acquireThreadOrWait(Runnable action) { try {
if (action == null) return null;
PooledThread t;
while (true) {
synchronized(this) {
if (_hasFreeAfterCreating()) {
t = _firstFreeThread();
break;
} else
_waitWaitWait();
}
}
t.addWork(action);
return t;
} catch (Exception __e) { throw rethrow(__e); } }
PooledThread _firstFreeThread() {
return first(free);
}
PooledThread _anyThread() {
return random(used);
}
class PooledThread extends Thread {
PooledThread(String name) { super(name); }
AppendableChain q;
synchronized Runnable _grabWorkOrSleep() { try {
Runnable r = first(q);
if (r == null) {
markFree(this);
if (verbose) print("Thread sleeps");
synchronized(this) { wait(); }
if (verbose) print("Thread woke up");
return null;
}
q = popFirst(q);
return r;
} catch (Exception __e) { throw rethrow(__e); } }
public void run() { try {
pingSource_tl().set(internalPingSource);
while (!retired()) { ping();
Runnable r = _grabWorkOrSleep();
if (verbose) print(this + " work: " + r);
if (r != null)
try {
if (verbose) print(this + " running: " + r);
r.run();
pingSource_tl().set(internalPingSource);
if (verbose) print(this + " done");
} catch (Throwable e) {
pingSource_tl().set(internalPingSource);
if (verbose) print(this + " error");
printStackTrace(e);
} finally {
pingSource_tl().set(internalPingSource);
if (verbose) print("ThreadPool finally");
}
}
} catch (Exception __e) { throw rethrow(__e); } }
synchronized boolean isEmpty() { return empty(q); }
// append to q (do later)
void addWork(Runnable r) {
if (verbose) print("Added work to " + this + ": " + r);
synchronized(this) {
q = chainPlus(q, r);
notifyAll();
}
}
}
PooledThread newThread() {
PooledThread t = new PooledThread("Thread Pool Inhabitant " + n2(total()+1));
t.start();
return t;
}
synchronized void markFree(PooledThread t) {
used.remove(t);
free.add(t);
notifyAll();
}
synchronized void markUsed(PooledThread t) {
free.remove(t);
used.add(t);
}
synchronized public String toString() {
return retired()
? "Retired ThreadPool"
: "ThreadPool " + roundBracket(commaCombine(
n2(used) + " used out of " + n2(total()),
max <= total() ? null : "could grow to " + n2(max)));
}
synchronized boolean retired() { return retired; }
synchronized void retire() {
if (verbose) print("ThreadPool Retiring");
retired = true;
for (var thread : free) syncNotifyAll(thread); // wake it up so it exits
}
void checkNotRetired() {
if (retired()) throw fail("retired");
}
// We could do a soft-close here (stop the idle threads, let running threads finish, then end those too, stop accepting new orders)
// or a hard close (interrupt all threads, stop accepting new orders)
synchronized public void close() { try {
retire();
} catch (Exception __e) { throw rethrow(__e); } }
// run in synchronized block
void _waitWaitWait() { try {
do {
fireCustomerMustWaitAlert();
wait();
checkNotRetired();
} while (empty(free));
} catch (Exception __e) { throw rethrow(__e); } }
void dO(String text, Runnable r) {
if (r == null) return;
new PingSource(this, text).dO(r);
}
ISleeper_v2 sleeper() { return sleeper; }
}
static class SynchronizedFloatBufferPresentingAsDoubles implements IDoubleBuffer {
float[] data;
int size;
SynchronizedFloatBufferPresentingAsDoubles() {}
SynchronizedFloatBufferPresentingAsDoubles(int size) { if (size != 0) data = new float[size]; }
SynchronizedFloatBufferPresentingAsDoubles(Iterable l) { addAll(l); }
SynchronizedFloatBufferPresentingAsDoubles(Collection l) { this(l(l)); addAll(l); }
SynchronizedFloatBufferPresentingAsDoubles(double... data) { this.data = doubleArrayToFloatArray(data); size = l(data); }
public synchronized void add(double i) {
if (size >= lFloatArray(data)) {
data = resizeFloatArray(data, Math.max(1, toInt(Math.min(maximumSafeArraySize(), lFloatArray(data)*2L))));
if (size >= data.length) throw fail(shortClassName(this) + " too large: " + size);
}
data[size++] = (float) i;
}
public synchronized void addAll(Iterable l) {
if (l != null) for (double i : l) add(i);
}
public synchronized double[] toArray() {
return size == 0 ? null : takeFirstFromFloatArrayAsDoubleArray(data, size);
}
double[] toArrayNonNull() {
return unnull(toArray());
}
synchronized List toList() {
return floatArrayToDoubleList(data, 0, size);
}
synchronized List asVirtualList() {
return new RandomAccessAbstractList() {
public int size() { return SynchronizedFloatBufferPresentingAsDoubles.this.size(); }
public Double get(int i) { return SynchronizedFloatBufferPresentingAsDoubles.this.get(i); }
public Double set(int i, Double val) {
synchronized(SynchronizedFloatBufferPresentingAsDoubles.this) {
Double a = get(i);
data[i] = val.floatValue();
return a;
}
}
};
}
synchronized void reset() { size = 0; }
void clear() { reset(); }
public synchronized int size() { return size; }
public synchronized boolean isEmpty() { return size == 0; }
public synchronized double get(int idx) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
return data[idx];
}
synchronized void set(int idx, double value) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
data[idx] = (float) value;
}
public synchronized double popLast() {
if (size == 0) throw fail("empty buffer");
return data[--size];
}
public synchronized double first() { return data[0]; }
public synchronized double last() { return data[size-1]; }
synchronized 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() {
synchronized(SynchronizedFloatBufferPresentingAsDoubles.this) {
//if (!hasNext()) fail("Index out of bounds: " + i);
return (double) 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; }
};
}*/
public synchronized void trimToSize() {
data = resizeFloatArray(data, size);
}
public synchronized int indexOf(double b) {
for (int i = 0; i < size; i++)
if (data[i] == (float) b)
return i;
return -1;
}
synchronized double[] subArray(int start, int end) {
return subFloatArrayAsDoubleArray(data, start, min(end, size));
}
public synchronized void insertAt(int idx, double[] l) {
int n = l(l);
if (n == 0) return;
float[] newData = new float[size+n];
arraycopy(data, 0, newData, 0, idx);
for (int i = 0; i < n; i++)
newData[idx+i] = (float) l[i];
arraycopy(data, idx, newData, idx+n, size-idx);
data = newData;
size = newData.length;
}
}
static class TradingSignal extends Meta {
final public TradingSignal setCoin(String coin){ return coin(coin); }
public TradingSignal coin(String coin) { this.coin = coin; return this; } final public String getCoin(){ return coin(); }
public String coin() { return coin; }
String coin;
final public TradingSignal setIsLong(boolean isLong){ return isLong(isLong); }
public TradingSignal isLong(boolean isLong) { this.isLong = isLong; return this; } final public boolean getIsLong(){ return isLong(); }
public boolean isLong() { return isLong; }
boolean isLong = false;
final public TradingSignal setTimestamp(Timestamp timestamp){ return timestamp(timestamp); }
public TradingSignal timestamp(Timestamp timestamp) { this.timestamp = timestamp; return this; } final public Timestamp getTimestamp(){ return timestamp(); }
public Timestamp timestamp() { return timestamp; }
Timestamp timestamp;
final public TradingSignal setAfterRun(TradingRun afterRun){ return afterRun(afterRun); }
public TradingSignal afterRun(TradingRun afterRun) { this.afterRun = afterRun; return this; } final public TradingRun getAfterRun(){ return afterRun(); }
public TradingRun afterRun() { return afterRun; }
TradingRun afterRun;
public String toString() {
String text = (isLong ? "Long" : "Short") + " signal "
+ (empty(coin) ? "" : "for " + coin + " ") + "at "
+ timestamp;
if (afterRun != null)
text += " after " + formatDouble2X(afterRun.changePercent()) + "% run";
return text;
}
// last candle before signal
TradingCandle candle() { return afterRun == null ? null : last(afterRun.candles); }
// Price at signal
double price() {
var candle = candle();
return candle == null ? Double.NaN : candle.end();
}
}
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(); }
final long toLong(){ return unixDate(); }
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));
}
}
interface ILongBuffer extends IntSize, Iterable, ILongQueue {
void add(long d);
void addAll(Iterable l);
long[] toArray();
long get(int idx);
void trimToSize();
long popLast();
long last();
boolean isEmpty();
List asVirtualList();
void insertAt(int idx, long[] l);
}
interface IDoubleBuffer extends IntSize, Iterable {
void add(double d);
void addAll(Iterable l);
double[] toArray();
double get(int idx);
void trimToSize();
double popLast();
double first();
double last();
boolean isEmpty();
void insertAt(int idx, double[] l);
int indexOf(double d);
default boolean contains(double d) { return indexOf(d) >= 0; }
}
abstract static class G22TradingStrategy extends ConceptWithChangeListeners implements Comparable, Juiceable {
static final String _fieldOrder = "verbose globalID customName comment q market mergePositionsForMarket cryptoCoin marginCoin primed usingLiveData doingRealTrades demoCoin active closedItself deactivated archived area adversity log epsilon cryptoStep minCrypto maxInvestment cellSize leverage marginPerPosition showClosedPositionsBackwards takeCoinProfit takeCoinProfitEnabled backDataHoursWanted backDataFed strategyJuicer logToPrint feedNote useDriftSystem driftSystem actualTicker cooldownMinutes digitizer direction maxDebt currentPrice oldPrice startingPrice startTime realizedProfit realizedCoinProfit realizedWins realizedCoinWins realizedLosses realizedCoinLosses stepCount stepSince openPositions closedPositions positionsThatFailedToOpen";
final String fieldsToReset_G22TradingStrategy(){ return fieldsToReset(); }
String fieldsToReset() {
return "\r\n globalID active\r\n q\r\n archived primed usingLiveData \r\n backDataFed startTime deactivated closedItself\r\n log currentTime currentPrice feedNote\r\n direction\r\n digitizer maxDebt direction oldPrice startingPrice\r\n maxInvestment\r\n realizedProfit realizedCoinProfit\r\n realizedWins realizedCoinWins\r\n realizedLosses realizedCoinLosses\r\n stepCount stepSince\r\n openPositions closedPositions positionsThatFailedToOpen\r\n drift driftSystem\r\n ";
}
final public G22TradingStrategy setVerbose(boolean verbose){ return verbose(verbose); }
public G22TradingStrategy verbose(boolean verbose) { this.verbose = verbose; return this; } final public boolean getVerbose(){ return verbose(); }
public boolean verbose() { return verbose; }
boolean verbose = false;
final public String getGlobalID(){ return globalID(); }
public String globalID() { return globalID; }
String globalID = aGlobalID();
// user-given name, overriding the technical name
final public G22TradingStrategy setCustomName(String customName){ return customName(customName); }
public G22TradingStrategy customName(String customName) { this.customName = customName; return this; } final public String getCustomName(){ return customName(); }
public String customName() { return customName; }
String customName;
// user-given comment
final public G22TradingStrategy setComment(String comment){ return comment(comment); }
public G22TradingStrategy comment(String comment) { this.comment = comment; return this; } final public String getComment(){ return comment(); }
public String comment() { return comment; }
String comment;
final public Q getQ(){ return q(); }
public Q q() { return q; }
transient Q q = startQ();
// link to market (optional)
final public G22TradingStrategy setMarket(IFuturesMarket market){ return market(market); }
public G22TradingStrategy market(IFuturesMarket market) { this.market = market; return this; } final public IFuturesMarket getMarket(){ return market(); }
public IFuturesMarket market() { return market; }
transient IFuturesMarket market;
final public G22TradingStrategy setMergePositionsForMarket(boolean mergePositionsForMarket){ return mergePositionsForMarket(mergePositionsForMarket); }
public G22TradingStrategy mergePositionsForMarket(boolean mergePositionsForMarket) { this.mergePositionsForMarket = mergePositionsForMarket; return this; } final public boolean getMergePositionsForMarket(){ return mergePositionsForMarket(); }
public boolean mergePositionsForMarket() { return mergePositionsForMarket; }
boolean mergePositionsForMarket = false;
public transient FieldVar varCryptoCoin_cache;
public FieldVar varCryptoCoin() { if (varCryptoCoin_cache == null) varCryptoCoin_cache = varCryptoCoin_load(); return varCryptoCoin_cache;}
public FieldVar varCryptoCoin_load() {
return new FieldVar