// now synchronized persistable sclass MultiBest { Cl best = new L; double score = negativeInfinity(); bool verboseNewBest; transient O stringifier; // func(A) -> S synchronized double bestScore() { ret best == null ? minusInfinity() : score; } bool isEmpty() { ret best.isEmpty(); } double score() { ret bestScore(); } double getScore() { ret bestScore(); } synchronized float floatScoreOr(float defaultValue) { ret best == null ? defaultValue : (float) score; } bool put(Pair p) { ret p != null && put(p.a, p.b); } bool put(Best b) { ret b != null && put(b!, b.score); } bool put(A a, double score) { ping(); bool change; if (a != null) synchronized(this) { if (score > this.score) { best.clear(); this.score = score; set change; } if (score >= this.score) { best.add(a); set change; } } if (change) { if (verboseNewBest) print("New best! " + this); pcallF(onChange); } ret change; } synchronized A get() { ret best; } synchronized bool has() { ret best != null; } synchronized Pair pair() { ret main pair(best, bestScore()); } synchronized Scored scored() { ret best == null ?: new Scored(best, bestScore()); } synchronized A getIfScoreAbove(double x) { ret score() >= x ? best : null; } toString { ret isEmpty() ? "-" : "Score " + formatDouble_significant2(score, 4) + (tied() ? ", " + nWinners(duplicity()) + ": " + joinWithComma(map stringify(best))); } S stringify(A a) { ret str(a); } bool tied() { ret duplicity() > 1; } int duplicity() { ret best.size(); } synchronized void clear() { best.clear(); score = 0; } }