diff options
| author | Franklin Wei <frankhwei536@gmail.com> | 2016-11-20 15:16:41 -0500 |
|---|---|---|
| committer | Franklin Wei <frankhwei536@gmail.com> | 2016-11-24 16:23:09 -0500 |
| commit | 56c9984511f016eab7e1278ba9e40d88bb59a162 (patch) | |
| tree | 1bfa6d3aeb3bf2a6ffec71387ac073cd0b8b2a51 /apps/plugins/puzzles/benchmark.pl | |
| parent | 29648f817677b84c03c2bcfe89eb8cf53653e7db (diff) | |
| download | rockbox-puzzles.zip rockbox-puzzles.tar.gz rockbox-puzzles.tar.bz2 rockbox-puzzles.tar.xz | |
[WIP] Port of Simon Tatham's Puzzle Collectionpuzzles
Original revision: 5123b1bf68777ffa86e651f178046b26a87cf2d9
MIT Licensed. Some games still crash and others are unplayable due to
issues with controls. Still need a "real" polygon filling algorithm.
The following games are at least partially broken for various reasons:
Cube: crash with certain settings
Galaxies: crash
Inertia: crash
Keen: input issues
Loopy: weird stuff happens
Map: crash on input
Mines: weird stuff happens on target
Palisade: input issues
Signpost: crash on input
Solo: input issues
Towers: input and drawing issues
Train Tracks: drawing issues
Twiddle: weird animation on target
Undead: input and drawing issues
Unequal: input and drawing issues
Untangle: input issues
All in all, about 40% of the games are at least partially broken.
Change-Id: I7c69b6860ab115f973c8d76799502e9bb3d52368
Diffstat (limited to '')
| -rwxr-xr-x | apps/plugins/puzzles/benchmark.pl | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/apps/plugins/puzzles/benchmark.pl b/apps/plugins/puzzles/benchmark.pl new file mode 100755 index 0000000..9876385 --- /dev/null +++ b/apps/plugins/puzzles/benchmark.pl @@ -0,0 +1,197 @@ +#!/usr/bin/perl + +# Process the raw output from benchmark.sh into Javascript-ified HTML. + +use strict; +use warnings; + +my @presets = (); +my %presets = (); +my $maxval = 0; + +while (<>) { + chomp; + if (/^(.*)(#.*): ([\d\.]+)$/) { + push @presets, $1 unless defined $presets{$1}; + push @{$presets{$1}}, $3; + $maxval = $3 if $maxval < $3; + } +} + +print <<EOF; +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ASCII" /> +<title>Puzzle generation-time benchmarks</title> +<script type="text/javascript"> +//<![CDATA[ +function choose_scale_ticks(scale) { + var nscale = 1, j = 0, factors = [2,2.5,2]; + while (scale / nscale > 20) { + nscale *= factors[j]; + j = (j+1) % factors.length; + } + return nscale; +} +function initPlots() { + var canvases = document.getElementsByTagName('canvas'); + for (var i = 0; i < canvases.length; i++) { + var canvas = canvases[i]; + var scale = eval(canvas.getAttribute("data-scale")); + var add = 20.5, mult = (canvas.width - 2*add) / scale; + var data = eval(canvas.getAttribute("data-points")); + var ctx = canvas.getContext('2d'); + ctx.lineWidth = '1px'; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.strokeStyle = ctx.fillStyle = '#000000'; + if (data === "scale") { + // Draw scale. + ctx.font = "16px sans-serif"; + ctx.textAlign = "center"; + ctx.textBaseline = "alphabetic"; + var nscale = choose_scale_ticks(scale); + for (var x = 0; x <= scale; x += nscale) { + ctx.beginPath(); + ctx.moveTo(add+mult*x, canvas.height); + ctx.lineTo(add+mult*x, canvas.height - 3); + ctx.stroke(); + ctx.fillText(x + "s", add+mult*x, canvas.height - 6); + } + } else { + // Draw a box plot. + function quantile(x) { + var n = (data.length * x) | 0; + return (data[n-1] + data[n]) / 2; + } + + var q1 = quantile(0.25), q2 = quantile(0.5), q3 = quantile(0.75); + var iqr = q3 - q1; + var top = 0.5, bot = canvas.height - 1.5, mid = (top+bot)/2; + var wlo = null, whi = null; // whisker ends + + ctx.strokeStyle = '#bbbbbb'; + var nscale = choose_scale_ticks(scale); + for (var x = 0; x <= scale; x += nscale) { + ctx.beginPath(); + ctx.moveTo(add+mult*x, 0); + ctx.lineTo(add+mult*x, canvas.height); + ctx.stroke(); + } + ctx.strokeStyle = '#000000'; + + for (var j in data) { + var x = data[j]; + if (x >= q1 - 1.5 * iqr && x <= q3 + 1.5 * iqr) { + if (wlo === null || wlo > x) + wlo = x; + if (whi === null || whi < x) + whi = x; + } else { + ctx.beginPath(); + ctx.arc(add+mult*x, mid, 2, 0, 2*Math.PI); + ctx.stroke(); + if (x >= q1 - 3 * iqr && x <= q3 + 3 * iqr) + ctx.fill(); + } + } + + ctx.beginPath(); + + // Box + ctx.moveTo(add+mult*q1, top); + ctx.lineTo(add+mult*q3, top); + ctx.lineTo(add+mult*q3, bot); + ctx.lineTo(add+mult*q1, bot); + ctx.closePath(); + + // Line at median + ctx.moveTo(add+mult*q2, top); + ctx.lineTo(add+mult*q2, bot); + + // Lower whisker + ctx.moveTo(add+mult*q1, mid); + ctx.lineTo(add+mult*wlo, mid); + ctx.moveTo(add+mult*wlo, top); + ctx.lineTo(add+mult*wlo, bot); + + // Upper whisker + ctx.moveTo(add+mult*q3, mid); + ctx.lineTo(add+mult*whi, mid); + ctx.moveTo(add+mult*whi, top); + ctx.lineTo(add+mult*whi, bot); + + ctx.stroke(); + } + } + document.getElementById('sort_orig').onclick = function() { + sort(function(e) { + return parseFloat(e.getAttribute("data-index")); + }); + }; + document.getElementById('sort_median').onclick = function() { + sort(function(e) { + return -parseFloat(e.getAttribute("data-median")); + }); + }; + document.getElementById('sort_mean').onclick = function() { + sort(function(e) { + return -parseFloat(e.getAttribute("data-mean")); + }); + }; +} +function sort(keyfn) { + var rows = document.getElementsByTagName("tr"); + var trs = []; + for (var i = 0; i < rows.length; i++) + trs.push(rows[i]); + trs.sort(function(a,b) { + var akey = keyfn(a); + var bkey = keyfn(b); + return akey < bkey ? -1 : akey > bkey ? +1 : 0; + }); + var parent = trs[0].parentElement; + for (var i = 0; i < trs.length; i++) + parent.removeChild(trs[i]); + for (var i = 0; i < trs.length; i++) + parent.appendChild(trs[i]); +} +//]]> +</script> +</head> +<body onLoad="initPlots();"> +<h1 align=center>Puzzle generation-time benchmarks</h1> +<p>Sort order: +<button id="sort_orig">Original</button> +<button id="sort_median">Median</button> +<button id="sort_mean">Mean</button> +<table> +<tr><th>Preset</th><td><canvas width=700 height=30 data-points='"scale"' data-scale="$maxval"></td></tr> +EOF + +my $index = 0; +for my $preset (@presets) { + my @data = sort { $a <=> $b } @{$presets{$preset}}; + my $median = ($#data % 2 ? + ($data[($#data-1)/2]+$data[($#data+1)/2])/2 : + $data[$#data/2]); + my $mean = 0; map { $mean += $_ } @data; $mean /= @data; + print "<tr data-index=\"$index\" data-mean=\"$mean\" data-median=\"$median\"><td>", &escape($preset), "</td><td><canvas width=700 height=15 data-points=\"["; + print join ",", @data; + print "]\" data-scale=\"$maxval\"></td></tr>\n"; + $index++; +} + +print <<EOF; +</body> +</html> +EOF + +sub escape { + my ($text) = @_; + $text =~ s/&/&/g; + $text =~ s/</</g; + $text =~ s/>/>/g; + return $text; +} |