sclass Scorer {
double score, total;
L successes, errors; // set to non-null if you want them filled
bool verboseFailures, verboseAll;
void addZeroToOne aka add(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); }
bool add(bool correct) {
++total;
if (correct) ++score;
ret correct;
}
bool add(bool correct, A info) {
main add(correct ? successes : errors, info);
if (verboseAll || verboseFailures && !correct)
_print((correct ? "[GOOD] " : "[BAD] ") + info);
ret add(correct);
}
// works if you use Scorer or Scorer
void eq(O a, O b) {
if (_eq(a, b))
add(true);
else
add(false, (A) (a + " != " + b));
}
void print() {
main print(toString());
}
toString {
ret formatDouble(ratioToPercent(score, total), 1) + "% correct (n=" + formatDouble(total, 1) + ")";
}
double get() {
ret ratioToPercent(score, total);
}
double percentScore() { ret get(); }
double score() { ret get(); }
bool allCorrect() {
ret score == total;
}
void add(Scorer scorer) {
if (scorer == null) ret;
total += scorer.total;
score += scorer.score;
addAll(successes, scorer.successes);
addAll(errors, scorer.errors);
}
void collectErrors() {
errors = new L;
}
void collectSuccesses() {
successes = new L;
}
}