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 javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
class main {
static class Scorer {
double score, total;
List successes, errors; // set to non-null if you want them filled
boolean verboseFailures, verboseAll;
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();
}
}
static float clamp(float x, float a, float b) {
return x < a ? a : x > b ? b : x;
}
static double clamp(double x, double a, double b) {
return x < a ? a : x > b ? b : x;
}
static int clamp(int x, int a, int b) {
return x < a ? a : x > b ? b : x;
}
static void add(BitSet bs, int i) {
bs.set(i);
}
static boolean add(Collection c, A a) {
return c != null && c.add(a);
}
static void add(Container c, Component x) {
addToContainer(c, x);
}
static A _print(String s, A a) {
return print(s, a);
}
static A _print(A a) {
return print(a);
}
static void _print() {
print();
}
static boolean _eq(Object a, Object b) {
return eq(a, b);
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
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