const co = require("co"); const ui = require("./ui"); const { text, trigrams, code } = require("./data"); const Stats = require("./stats"); const Cluster = require("./cluster"); const Population = require("./population"); const { JCUKEN, Diktor, Diktor_VoronovMod, Redaktor, JUIYAF, Zubachev, Ruhal, } = require("./presets"); const { use_elites, mutate_levels, mutate_thresholds, max_no_chage, max_generation, population_size, POPULATION_SIZE, } = require("./config"); let { mutate_level } = require("./config"); const data = text; const cluster = new Cluster(data); const seed_layouts = [ JCUKEN, Diktor, Diktor_VoronovMod, Redaktor, JUIYAF, Zubachev, Ruhal, ]; co(boot).catch((e) => console.log(e.stack)); function* boot() { if (mutate_levels.length != mutate_thresholds.length) { die("Mutate settings are incorrect"); } for (const promise of cluster.schedule(seed_layouts)) { const { layout, result } = yield promise; ui.addResult(layout, new Stats(result)); } yield start(Population.random(), max_generation); } function* start(population, count) { let last_layout, last_score, no_changes_in; let rank = 0; for (let i = 0; i < count; i++) { const [layout, score] = yield handle(population); if (!last_layout || last_layout.toString() !== layout.toString()) { no_changes_in = 0; if (rank < mutate_levels.length) { if (score.total > mutate_thresholds[rank]) { mutate_level = mutate_levels[rank]; rank++; } } } else { no_changes_in++; } ui.addResult(layout, score, no_changes_in, max_no_chage); last_layout = layout; last_score = score; if (no_changes_in == max_no_chage) { break; } population = population.next({ elite: use_elites, mutate: mutate_level }); } const vs = ui.vs_result(last_score); const overheads = ui.getOverheads(); ui.destroy(); const fs = require("fs"); const file = new console.Console( fs.createWriteStream(`./results/output${new Date().getTime()}.txt`) ); console.log(`Total: ${last_score.total}, Dist: ${last_score.position},\n`); console.log( `Symmetry: ${last_score.symmetry}%, Evenness: ${last_score.evenness}%,\n` ); console.log( `Hands: ${last_score.handsUsage.map((v) => v + "%").join(" | ")},\n` ); console.log( `Overheads: Finger:${overheads.finger}%, Hand:${overheads.hand}%, Shift:${overheads.shift}%\n` ); console.log(`Fingers ${last_score.fingersUsage}\n`); console.log(`vs.Diktor: ${vs[0]}`); console.log(`vs.JCUKEN: ${vs[1]}\n`); console.log(last_layout.toCyrillic(), "\n"); console.log(last_layout.config); file.log(`Total: ${last_score.total}, Dist: ${last_score.position},\n`); file.log( `Symmetry: ${last_score.symmetry}%, Evenness: ${last_score.evenness}%,\n` ); file.log( `Hands: ${last_score.handsUsage.map((v) => v + "%").join(" | ")},\n` ); file.log( `Overheads: Finger:${overheads.finger}%, Hand:${overheads.hand}%, Shift:${overheads.shift}%\n` ); file.log(`Fingers ${last_score.fingersUsage}\n`); file.log(`vs.Diktor: ${vs[0]}`); file.log(`vs.JCUKEN: ${vs[1]}\n`); file.log(last_layout.toCyrillic(), "\n"); file.log(last_layout.config); } function* handle(population) { ui.newPopulation( population, max_generation, use_elites, mutate_level, POPULATION_SIZE ); const layouts = population.genomes.map((g) => g.toLayout()); for (const promise of cluster.schedule(layouts)) { const { layout, result } = yield promise; const score = new Stats(result); ui.logGrade(layout, score); layouts.forEach((l, i) => { if (l.config === layout.config) { population.scores[i] = score; } }); } const best_gene = population.best(); const best_layout = best_gene.toLayout(); const score = population.scoreFor(best_gene); return [best_layout, score]; }