const { log } = require("console"); const RollCheck = require("./RollCheck"); const StatRoll = require("./StatRoll"); const { stat } = require("fs"); const ResultStatistics = require("./ResultStatistics"); module.exports = class Checker { /** * @type {RollCheck[]} */ checks = []; /** * @type {int[]} */ amounts; /** * @type {int} */ attemts; /** * @type {boolean} */ #isPrepared = false; /** * @type {ResultStatistics} */ statistic_all; /** * @type {ResultStatistics} */ statistic_passed; variants = {}; full_mask; /** * @param {string} name * @param {(roll: StatRoll) => boolean} fn */ addCheck(name, fn) { if (this.#isPrepared) { console.log("Cannot add check while prepared"); } this.checks.push(new RollCheck(name, fn)); } prepare() { this.amounts = Array.from({length: Math.pow(2, this.checks.length)}, _ => 0); this.#isPrepared = true; this.attemts = 0; this.statistic_all = new ResultStatistics(); this.statistic_passed = new ResultStatistics(); } /** * * @param {StatRoll} statRoll */ test(statRoll) { let mask = 0; for (let i = 0; i < this.checks.length; i++) { const check = this.checks[i]; const checkResult = check.test(statRoll); mask += checkResult ? Math.pow(2, i) : 0; } this.amounts[mask] += 1; this.attemts += 1; this.statistic_all.add(statRoll); if (mask + 1 === this.amounts.length) { this.statistic_passed.add(statRoll); } } printResults() { this.statistic_all.print(this.attemts); const resultPerCheck = []; for (let i = 0; i < this.checks.length; i++) { const check = this.checks[i]; const amount = this.amounts.filter((_, mask) => (mask >> i) % 2 > 0).reduce((a, s) => s + a); resultPerCheck.push({ check: check.name, successes: amount, successes_percent: 100 * amount / this.attemts, fails: this.attemts - amount, fails_percent: 100 * (this.attemts - amount) / this.attemts, }) } console.table(resultPerCheck); const result = []; for (let mask = 0; mask < this.amounts.length; mask++) { const amount = this.amounts[mask]; result.push({ mask: mask.toString(2), successes: this.checks.filter((_, i) => (mask >> i) % 2 > 0).map(f => f.name).join(', '), fails: this.checks.filter((_, i) => (mask >> i) % 2 === 0).map(f => f.name).join(', '), amount: amount, percent: 100 * amount / this.attemts, }); } console.table(result); this.statistic_passed.print(this.amounts[this.amounts.length - 1]); } }