change logging api to accept variadic properties
This commit is contained in:
parent
336efff5c1
commit
aab2e60dab
7 changed files with 61 additions and 23 deletions
|
@ -6,5 +6,5 @@ export type GuessResult = { kind: "success" } | { kind: "failure"; informations:
|
||||||
|
|
||||||
export interface Gaming {
|
export interface Gaming {
|
||||||
length(): number;
|
length(): number;
|
||||||
guess(guess: string, known: string): Awaitable<GuessResult>;
|
guess(guess: string): Awaitable<GuessResult>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export class ManualProxy implements Gaming {
|
||||||
this.word_length = length;
|
this.word_length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
guess(guess: string, _known: string): Awaitable<GuessResult> {
|
guess(guess: string): Awaitable<GuessResult> {
|
||||||
console.log("<proxy> Guessing:", guess);
|
console.log("<proxy> Guessing:", guess);
|
||||||
const result = read_until_correct(this.word_length);
|
const result = read_until_correct(this.word_length);
|
||||||
console.log();
|
console.log();
|
||||||
|
|
|
@ -15,7 +15,7 @@ export class Simulator implements Gaming {
|
||||||
return new Simulator(word);
|
return new Simulator(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
guess(guess: string, _known: string): GuessResult {
|
guess(guess: string): GuessResult {
|
||||||
if (guess === this.word) return { kind: "success" };
|
if (guess === this.word) return { kind: "success" };
|
||||||
const informations = info_of_guess(guess, this.word);
|
const informations = info_of_guess(guess, this.word);
|
||||||
return { kind: "failure", informations };
|
return { kind: "failure", informations };
|
||||||
|
|
|
@ -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<GuessResult>) {
|
async guess(try_: (guess: string, known: string) => Awaitable<GuessResult>) {
|
||||||
const res = this.expected_result();
|
const res = this.expected_result();
|
||||||
if (res.completed) return await try_(res.result, res.result);
|
if (res.completed) return await try_(res.result, res.result);
|
||||||
|
|
|
@ -2,5 +2,6 @@ import { GuessResult } from "../game/game.ts";
|
||||||
import { Awaitable } from "../utils.ts";
|
import { Awaitable } from "../utils.ts";
|
||||||
|
|
||||||
export interface Guessing {
|
export interface Guessing {
|
||||||
guess(try_: (guess: string, known: string) => Awaitable<GuessResult>): Promise<GuessResult | null>;
|
declare_properties(): string[];
|
||||||
|
guess(try_: (guess: string, ...properties: unknown[]) => Awaitable<GuessResult>): Promise<GuessResult | null>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,14 @@ export class ReducingGuesser implements Guessing {
|
||||||
this.candidates = new Set(this.words.values());
|
this.candidates = new Set(this.words.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async guess(try_: (guess: string, known: string) => Awaitable<GuessResult>) {
|
public declare_properties() {
|
||||||
if (this.candidates.size === 1) return await try_(first(this.candidates)!, "");
|
return ["candidates"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async guess(try_: (guess: string, candidates: number) => Awaitable<GuessResult>) {
|
||||||
|
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 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;
|
if (result.kind === "success") return result;
|
||||||
this.learn(guess, result.informations);
|
this.learn(guess, result.informations);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists
|
||||||
|
|
||||||
import { Guessing } from "./guesser/guesser.ts";
|
import { Guessing } from "./guesser/guesser.ts";
|
||||||
import { Gaming, GuessResult } from "./game/game.ts";
|
import { Gaming, GuessResult } from "./game/game.ts";
|
||||||
import { last, wait } from "./utils.ts";
|
import { last, wait, zip } from "./utils.ts";
|
||||||
|
|
||||||
export class Runner<Ga extends Gaming, Gu extends Guessing> {
|
export class Runner<Ga extends Gaming, Gu extends Guessing> {
|
||||||
game;
|
game;
|
||||||
|
@ -22,10 +22,10 @@ export class Runner<Ga extends Gaming, Gu extends Guessing> {
|
||||||
async play_all() {
|
async play_all() {
|
||||||
this.logging.on_start(this.game.length());
|
this.logging.on_start(this.game.length());
|
||||||
while (true) {
|
while (true) {
|
||||||
const result = await this.guesser.guess(async (guess, known) => {
|
const result = await this.guesser.guess(async (guess, ...properties) => {
|
||||||
const result = await this.game.guess(guess, known);
|
const result = await this.game.guess(guess);
|
||||||
this.turns.push({ guess, result });
|
this.turns.push({ guess, result });
|
||||||
this.logging.on_guess(known, guess, result);
|
this.logging.on_guess(guess, result, ...properties);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
if (result !== null) break;
|
if (result !== null) break;
|
||||||
|
@ -49,18 +49,29 @@ function format_result(result: GuessResult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LoggingStrategy {
|
interface LoggingStrategy {
|
||||||
on_start(length: number): void;
|
on_start(length: number, ...properties: string[]): void;
|
||||||
on_guess(known: string, guess: string, result: GuessResult): void;
|
on_guess(guess: string, result: GuessResult, ...properties: unknown[]): void;
|
||||||
on_finish(turns: Turn[]): void;
|
on_finish(turns: Turn[]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VerboseLogging implements LoggingStrategy {
|
export class VerboseLogging implements LoggingStrategy {
|
||||||
on_start(_length: number) {}
|
properties;
|
||||||
|
length;
|
||||||
|
|
||||||
on_guess(known: string, guess: string, result: GuessResult): void {
|
constructor() {
|
||||||
console.log(" Knows:", known);
|
this.length = 0;
|
||||||
console.log("Guessing:", guess);
|
this.properties = [] as string[];
|
||||||
console.log(" Got:", format_result(result));
|
}
|
||||||
|
|
||||||
|
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();
|
console.log();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,17 +82,35 @@ export class VerboseLogging implements LoggingStrategy {
|
||||||
console.log("With", last_.result.kind, ".");
|
console.log("With", last_.result.kind, ".");
|
||||||
console.log("In", turns.length, "steps");
|
console.log("In", turns.length, "steps");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_entry(name: string, value: unknown) {
|
||||||
|
console.log(name.padStart(this.length) + ": " + value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableLogging implements LoggingStrategy {
|
export class TableLogging implements LoggingStrategy {
|
||||||
on_start(length: number): void {
|
columns;
|
||||||
const pad = (title: string) => title.padEnd(length);
|
|
||||||
console.log(`${pad("known")}\t${pad("guess")}\t${pad("result")}`);
|
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();
|
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 {
|
on_finish(turns: Turn[]): void {
|
||||||
const last_ = last(turns);
|
const last_ = last(turns);
|
||||||
assertExists(last_);
|
assertExists(last_);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue