!752 p { L texts = splitAtSpace("a b c d"); data = litorderedmap(); for (S s : texts) data.put(renderTheText(s), s); push("Dummy"); push("MD5Recognizer"); solveImage2Text(); } static class Dummy { O get(BWImage img) { ret "dummy"; } } static class MD5Recognizer { new Map map; O get(BWImage img) { ret map.get(md5OfBWImage(img)); } void train(Map data) { for (BWImage img : keys(data)) { S text = data.get(img); map.put(md5OfBWImage(img), text); } } } static Font renderTheText_font; static BWImage renderTheText(S s) { if (renderTheText_font == null) renderTheText_font = loadFont("#1004569"); // "Ticketing" ret new BWImage(renderText(renderTheText_font, 20f, s)); } static void push(S solver) { newProducts.add(solver); } // solvers are func(BWImage) -> S static Map data; static new LinkedBlockingQueue newProducts; static new Best best; sclass Best { S solver; double score; void update(S solver, double score) { if (score > this.score) { print("New best score: " + score); this.score = score; this.solver = solver; } } } static void solveImage2Text() { while licensed { testSolver(grabFromQueue(newProducts)); } } static void testSolver(S solver) { O realSolver = unstructure(solver); train(realSolver, data); double score = score(realSolver, data); print(formatDouble(score, 1) + ": " + solver); best.update(solver, score); } static void train(O realSolver, Map data) { callOpt(realSolver, "train", data); } static double score(O realSolver, Map data) { double score = 0; int n = 0; for (BWImage img : keys(data)) { S text = data.get(img); ++n; try { if (eq(callF(realSolver, img), text)) ++score; } catch e { silentException(e); } } ret score*100/n; }