// A = compressor type (e.g. s), Data = data type persistable sclass CompressionSearch_AnyType extends Probabilistic { // user-set settable CompressionRegime_AnyType regime; settable Data inputData; event onNewBest; // public output variables new Best best; new L strategies; *() { init(); } *(CompressionRegime_AnyType *regime) { init(); } *(CompressionRegime_AnyType *regime, Data *inputData) { init(); } void init { best.onChange = r newBest; } // can submit concurrently! Submission submit(A compression, O notes default null) { ret _submit(compression, notes); } // private (although Submission is returned) class Submission { settable O notes; toString { ret linesLL( "Compressor " + (correct() ? "correct" : "incorrect"), "Compression factor " + score(), "Code:", indentx(str(decompressor())), "Code as bytes:", indentx(bytesToHex(compressed())) ); } void setDecompressor(A decompressor) { this.decompressor_cache = decompressor; } Data inputData() { ret inputData; } simplyCached byte[] compressed() { ret decompressor_cache == null ?: regime.decompressorToBytes(decompressor_cache); } simplyCached A decompressor() { ret compressed_cache == null ?: regime.decompressorFromBytes(compressed_cache); } int compressedSize() { ret l(compressed()); } simplyCached double score() { ret doubleRatio(inputDataSize(), compressedSize()); } bool decompressed; O decompressedValue; O decompressed() { if (!decompressed) { decompressedValue = regime.runDecompressor(decompressor()); set decompressed; } ret decompressedValue; } simplyCached Bool correct() { ret eq(toByteList(decompressed()), inputData()); } } int inputDataSize() { ret l(inputData); } Submission _submit(A compression, O notes) { if (compression == null) null; new Submission s; s.notes(notes); s.setDecompressor(compression); if (s.score() > best.score()) if (!s.correct()) warn("Compressor didn't verify"); else best.put(s, s.score()); ret s; } Submission bestSubmission() { methodForEach flush(strategies); ret best!; } A bestCompression aka get() { var s = bestSubmission(); ret s?.decompressor(); } void addStrategy(AbstractCompressor_AnyType compressor) { if (compressor == null) ret; initAction(compressor); compressor.setSearch(this); strategies.add(compressor); compressor.run(); } run {} }