From aab2e60dab19faac73b4ce90d79faaf618328536 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Thu, 2 May 2024 16:14:15 +0200 Subject: [PATCH] change logging api to accept variadic properties --- src/lib/game/game.ts | 2 +- src/lib/game/proxy.ts | 2 +- src/lib/game/simulator.ts | 2 +- src/lib/guesser/base.ts | 4 +++ src/lib/guesser/guesser.ts | 3 +- src/lib/guesser/reducing.ts | 10 ++++-- src/lib/runner.ts | 61 +++++++++++++++++++++++++++---------- 7 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/lib/game/game.ts b/src/lib/game/game.ts index e6acbe4..0fff3c5 100644 --- a/src/lib/game/game.ts +++ b/src/lib/game/game.ts @@ -6,5 +6,5 @@ export type GuessResult = { kind: "success" } | { kind: "failure"; informations: export interface Gaming { length(): number; - guess(guess: string, known: string): Awaitable; + guess(guess: string): Awaitable; } diff --git a/src/lib/game/proxy.ts b/src/lib/game/proxy.ts index ced5f21..7bbbdf0 100644 --- a/src/lib/game/proxy.ts +++ b/src/lib/game/proxy.ts @@ -10,7 +10,7 @@ export class ManualProxy implements Gaming { this.word_length = length; } - guess(guess: string, _known: string): Awaitable { + guess(guess: string): Awaitable { console.log(" Guessing:", guess); const result = read_until_correct(this.word_length); console.log(); diff --git a/src/lib/game/simulator.ts b/src/lib/game/simulator.ts index 045abbc..8fc8028 100644 --- a/src/lib/game/simulator.ts +++ b/src/lib/game/simulator.ts @@ -15,7 +15,7 @@ export class Simulator implements Gaming { return new Simulator(word); } - guess(guess: string, _known: string): GuessResult { + guess(guess: string): GuessResult { if (guess === this.word) return { kind: "success" }; const informations = info_of_guess(guess, this.word); return { kind: "failure", informations }; diff --git a/src/lib/guesser/base.ts b/src/lib/guesser/base.ts index c03bbdc..099f2b0 100644 --- a/src/lib/guesser/base.ts +++ b/src/lib/guesser/base.ts @@ -26,6 +26,10 @@ export class BaseGuesser implements Guessing { } } + declare_properties(): string[] { + return ["known".padStart(this.length)]; + } + async guess(try_: (guess: string, known: string) => Awaitable) { const res = this.expected_result(); if (res.completed) return await try_(res.result, res.result); diff --git a/src/lib/guesser/guesser.ts b/src/lib/guesser/guesser.ts index 5fba2ac..a0f202c 100644 --- a/src/lib/guesser/guesser.ts +++ b/src/lib/guesser/guesser.ts @@ -2,5 +2,6 @@ import { GuessResult } from "../game/game.ts"; import { Awaitable } from "../utils.ts"; export interface Guessing { - guess(try_: (guess: string, known: string) => Awaitable): Promise; + declare_properties(): string[]; + guess(try_: (guess: string, ...properties: unknown[]) => Awaitable): Promise; } diff --git a/src/lib/guesser/reducing.ts b/src/lib/guesser/reducing.ts index 2785352..3edf5fb 100644 --- a/src/lib/guesser/reducing.ts +++ b/src/lib/guesser/reducing.ts @@ -18,10 +18,14 @@ export class ReducingGuesser implements Guessing { this.candidates = new Set(this.words.values()); } - public async guess(try_: (guess: string, known: string) => Awaitable) { - if (this.candidates.size === 1) return await try_(first(this.candidates)!, ""); + public declare_properties() { + return ["candidates"]; + } + + public async guess(try_: (guess: string, candidates: number) => Awaitable) { + if (this.candidates.size === 1) return await try_(first(this.candidates)!, this.candidates.size); const guess = get_word_with_smallest_cuts(this.candidates, this.words); - const result = await try_(guess, ""); + const result = await try_(guess, this.candidates.size); if (result.kind === "success") return result; this.learn(guess, result.informations); return null; diff --git a/src/lib/runner.ts b/src/lib/runner.ts index 8d20cad..60c3254 100644 --- a/src/lib/runner.ts +++ b/src/lib/runner.ts @@ -2,7 +2,7 @@ import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists import { Guessing } from "./guesser/guesser.ts"; import { Gaming, GuessResult } from "./game/game.ts"; -import { last, wait } from "./utils.ts"; +import { last, wait, zip } from "./utils.ts"; export class Runner { game; @@ -22,10 +22,10 @@ export class Runner { async play_all() { this.logging.on_start(this.game.length()); while (true) { - const result = await this.guesser.guess(async (guess, known) => { - const result = await this.game.guess(guess, known); + const result = await this.guesser.guess(async (guess, ...properties) => { + const result = await this.game.guess(guess); this.turns.push({ guess, result }); - this.logging.on_guess(known, guess, result); + this.logging.on_guess(guess, result, ...properties); return result; }); if (result !== null) break; @@ -49,18 +49,29 @@ function format_result(result: GuessResult) { } interface LoggingStrategy { - on_start(length: number): void; - on_guess(known: string, guess: string, result: GuessResult): void; + on_start(length: number, ...properties: string[]): void; + on_guess(guess: string, result: GuessResult, ...properties: unknown[]): void; on_finish(turns: Turn[]): void; } export class VerboseLogging implements LoggingStrategy { - on_start(_length: number) {} + properties; + length; - on_guess(known: string, guess: string, result: GuessResult): void { - console.log(" Knows:", known); - console.log("Guessing:", guess); - console.log(" Got:", format_result(result)); + constructor() { + this.length = 0; + this.properties = [] as string[]; + } + + on_start(_length: number, ...properties: string[]) { + this.length = Math.max(8, ...properties.map((p) => p.length)); + this.properties = properties; + } + + on_guess(guess: string, result: GuessResult, ...properties: unknown[]): void { + for (const [name, value] of zip(this.properties, properties)) this.log_entry(name, value); + this.log_entry("Guessing", guess); + this.log_entry("Got", format_result(result)); console.log(); } @@ -71,17 +82,35 @@ export class VerboseLogging implements LoggingStrategy { console.log("With", last_.result.kind, "."); console.log("In", turns.length, "steps"); } + + log_entry(name: string, value: unknown) { + console.log(name.padStart(this.length) + ": " + value); + } } export class TableLogging implements LoggingStrategy { - on_start(length: number): void { - const pad = (title: string) => title.padEnd(length); - console.log(`${pad("known")}\t${pad("guess")}\t${pad("result")}`); + columns; + + constructor() { + this.columns = [] as (readonly [string, number])[]; + } + + on_start(length: number, ...properties: string[]): void { + this.columns = properties.map((p) => [p, p.length] as const); + this.columns.splice(0, 0, ["guess", length], ["result", length]); + let line = ""; + for (const [name, width] of this.columns) line += name.padStart(width) + " "; + console.log(line); console.log(); } - on_guess(known: string, guess: string, result: GuessResult): void { - console.log(`${known}\t${guess}\t${format_result(result)}`); + + on_guess(guess: string, result: GuessResult, ...properties: unknown[]): void { + const properties_ = [guess, format_result(result), ...properties]; + let line = ""; + for (const [[_, width], value] of zip(this.columns, properties_)) line += `${value}`.padStart(width) + " "; + console.log(line); } + on_finish(turns: Turn[]): void { const last_ = last(turns); assertExists(last_);