import math, random, strformat, strutils, times, std/monotimes import fixedseq, game, simulation type TestResults = object ops: int time: Duration proc formatNum(n: SomeNumber, decimals = 0): string = when n is SomeFloat: let s = $n.round(decimals) else: let s = $n var parts = s.split('.') result = parts[0].insertSep(',') if decimals > 0: result = result & '.' & parts[1] proc summarize(tr: TestResults, opname = "operations") = let secs = tr.time.inMilliseconds.float / 1000 stdout.write("Test completed:\n") stdout.write(&" {tr.ops.formatNum} {opname} in {secs.formatNum} seconds\n") stdout.write(&" {(tr.ops.float / secs).formatNum} {opname} per second") stdout.flushFile() template executionTime(body: untyped): Duration = let start = getMonoTime() body getMonoTime() - start proc getRand(): Rand = randomize() result = initRand(rand(int64)) proc randomDice(r: var Rand): seq[tuple[c: Color, p: int]] = for c in Color: let v = r.rand(1..3) result.add((c, v)) result.shuffle proc newRandomGame(r: var Rand): Board = var dice: array[5, tuple[c: Color, p: int]] for i in 0 .. 4: dice[i] = (Color(i), r.rand(1..3)) result.init result.setState(dice, []) proc games(nTests, nSamples: Natural, parallel = true) = var r = getRand() var scores: ScoreSet var res: TestResults for i in 1 .. nTests: let b = newRandomGame(r) let dur = executionTime: let s = b.randomGames(nSamples, parallel = parallel) scores.update(s) res.ops += s.sum() res.time += dur res.summarize("games") proc legs(nTests: Natural) = var r = getRand() var scores: ScoreSet var res: TestResults for i in 1 .. nTests: let b = newRandomGame(r) let dur = executionTime: let s = b.getLegScores scores.update(s) res.ops += s.sum res.time += dur res.summarize("legs") proc spread(nTests, nSamples: Natural) = var r = getRand() let b = newRandomGame(r) let spread = randomSpread(b, nTests, nSamples) stdout.writeLine("Variance:") for c in Color: let variance = 100 * (spread.hi[c] - spread.lo[c]) stdout.writeLine(fmt"{c}: {round(variance, 2):.2f}%") let diff = 100 * (max(spread.hi) - min(spread.lo)) stdout.writeLine(fmt"Win percentage differential: {round(diff, 2):.2f}%") stdout.flushFile() when isMainModule: legs(3000)