Skip to content

Commit 7d11a9a

Browse files
author
Tythos
committed
Working!
1 parent a4e7695 commit 7d11a9a

File tree

12 files changed

+5703
-2
lines changed

12 files changed

+5703
-2
lines changed

README.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

README.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
KIFIEW
2+
======
3+
4+
Basic Kifu viewer (SGF format) web application. Download games from, among other
5+
possible sources, GoKifu (http://gokifu.com), then drag-and-drop them into the
6+
appropriately-labeled region of the web application. Can be run with a static
7+
file server or locally, direct from *index.html*.

img/favicon.ico

16.6 KB
Binary file not shown.

index.css

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
*/
3+
4+
.clearfix:after {
5+
content: ".";
6+
display: block;
7+
height: 0;
8+
clear: both;
9+
visibility: hidden;
10+
}
11+
12+
body {
13+
margin: 0;
14+
}
15+
16+
button {
17+
width: 128px;
18+
margin-left: 128px;
19+
}
20+
21+
path {
22+
stroke: #000;
23+
shape-rendering: crispedges;
24+
}
25+
26+
.xAxis text {
27+
dominant-baseline: hanging;
28+
text-anchor: middle;
29+
}
30+
31+
.yAxis text {
32+
dominant-baseline: middle;
33+
text-anchor: end;
34+
}
35+
36+
.metaField {
37+
text-align: right;
38+
font-weight: bold;
39+
}
40+
41+
.metaValue {
42+
font-style: italic;
43+
}
44+
45+
.left {
46+
float: left;
47+
margin-top: 50px;
48+
}
49+
50+
.right {
51+
float: left;
52+
margin-top: 80px;
53+
height: 800px;
54+
overflow-y: scroll;
55+
}
56+
57+
#wrapper {
58+
width: 640px;
59+
margin: 100px auto 0 auto;
60+
}
61+
62+
#board {
63+
width: 640px;
64+
height: 640px;
65+
}
66+
67+
#history {
68+
margin: 0 auto 50px auto;
69+
width: 256px;
70+
text-align: center;
71+
}
72+
73+
#load {
74+
text-align: center;
75+
font-family: sans-serif;
76+
font-size: 16pt;
77+
font-weight: bold;
78+
margin: 25px auto 0 auto;
79+
}
80+
81+
#meta {
82+
width: 500px;
83+
margin: 25px auto 0 auto;
84+
font-size: 10pt;
85+
}
86+
87+
#pieces text {
88+
dominant-baseline: middle;
89+
text-anchor: middle;
90+
font-family: sans-serif;
91+
font-size: 8pt;
92+
font-weight: bold;
93+
}
94+
95+
#historyTitle {
96+
text-align: center;
97+
font-weight: bold;
98+
font-size: 16pt;
99+
}

index.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>KIFIEW</title>
5+
<meta charset="utf-8"/>
6+
<link rel="stylesheet" href="index.css" type="text/css"/>
7+
<link rel="icon" href="img/favicon.ico" type="image/x-icon"/>
8+
<script type="text/javascript" src="src/require.js" data-main="src/main"></script>
9+
</head>
10+
<body>
11+
<div class="clearfix">
12+
<div class="left">
13+
<h1 id="load">(Drop SGF Here)</h1>
14+
<table id="meta"><tbody></tbody></table>
15+
<svg id="board"></svg><br/>
16+
<button id="prev">&laquo; Prev</button>
17+
<button id="next">Next &raquo;</button>
18+
</div>
19+
<div class="right">
20+
<h2>Move History</h2>
21+
<table id="history">
22+
<thead>
23+
<tr>
24+
<th>Move</th>
25+
<th>Position</th>
26+
</tr>
27+
</thead>
28+
<tbody>
29+
</tbody>
30+
</table>
31+
</div>
32+
</div>
33+
</body>
34+
</html>

src/Board.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
*/
3+
4+
define(function(require, exports, module) {
5+
var Kifu = require("Kifu");
6+
var d3 = require("d3.min");
7+
var numeric = require("numeric");
8+
9+
function splice(x, y) {
10+
if (x.length != y.length) {
11+
console.error("Splice input dimensions must match");
12+
}
13+
return x.map(function(_, i) {
14+
return [x[i], y[i]];
15+
});
16+
}
17+
18+
function Board() {
19+
this.kifu = new Kifu();
20+
this.alphaOffset = "A".charCodeAt();
21+
return this;
22+
}
23+
24+
Board.prototype.renderMove = function(pieces) {
25+
/*
26+
*/
27+
var coords = this.kifu.translateCoords(this.kifu.currentMove);
28+
var side = this.kifu.currentMove % 2 == 0 ? "B" : "W";
29+
var point = pieces.querySelector("#_" + coords[0] + coords[1]);
30+
var label = pieces.querySelector("#__" + coords[0] + coords[1]);
31+
if (side.toUpperCase() == "B") {
32+
d3.select(point)
33+
.attr("stroke", "black")
34+
.attr("fill", "black");
35+
d3.select(label)
36+
.attr("fill", "white")
37+
.text(this.kifu.currentMove + 1);
38+
} else if (side.toUpperCase() == "W") {
39+
d3.select(point)
40+
.attr("stroke", "black")
41+
.attr("fill", "white");
42+
d3.select(label)
43+
.attr("fill", "black")
44+
.text(this.kifu.currentMove + 1);
45+
}
46+
};
47+
48+
Board.prototype.renderUnmove = function(pieces) {
49+
/* Removes piece added by the current move index.
50+
*/
51+
var coords = this.kifu.translateCoords(this.kifu.currentMove);
52+
var side = this.kifu.currentMove % 2 == 0 ? "B" : "W";
53+
var point = pieces.querySelector("#_" + coords[0] + coords[1]);
54+
var label = pieces.querySelector("#__" + coords[0] + coords[1]);
55+
d3.select(point)
56+
.attr("stroke", "none")
57+
.attr("fill", "none");
58+
d3.select(label)
59+
.attr("fill", "none")
60+
.text("");
61+
};
62+
63+
Board.prototype.render = function(svg) {
64+
/*
65+
*/
66+
var svg = d3.select(svg);
67+
var width = parseInt(svg.style("width"));
68+
var height = parseInt(svg.style("height"));
69+
var I = 19, J = 19;
70+
var margin = { top: 0.05, right: 0.05, bottom: 0.05, left: 0.05 };
71+
72+
var xScale = d3.scaleLinear()
73+
.domain([0, I-1])
74+
.range([width*margin.left, width*(1-margin.right)]);
75+
var yScale = d3.scaleLinear()
76+
.domain([0, J-1])
77+
.range([height*(1-margin.bottom), height*margin.top]);
78+
var line = d3.line()
79+
.x(function(d) { return xScale(d[0]); })
80+
.y(function(d) { return yScale(d[1]); });
81+
82+
var xi = numeric.linspace(0, I-1);
83+
var yi = numeric.linspace(0, J-1);
84+
var x0 = (new Array(I)).fill(0);
85+
var y0 = (new Array(J)).fill(0);
86+
var grid = svg.append("g");
87+
for (var i = 0; i < I; i++) {
88+
var xy = splice(numeric.add(x0, i), yi);
89+
grid.append("path").attr("d", line(xy));
90+
}
91+
for (var j = 0; j < J; j++) {
92+
var xy = splice(xi, numeric.add(y0, j));
93+
grid.append("path").attr("d", line(xy));
94+
}
95+
96+
var xAxis = svg.append("g").classed("xAxis", true);
97+
for (var i = 0; i < I; i++) {
98+
xAxis.append("text")
99+
.text(String.fromCharCode(i + this.alphaOffset))
100+
.attr("x", xScale(i))
101+
.attr("y", yScale(0));
102+
}
103+
var yAxis = svg.append("g").classed("yAxis", true);
104+
for (var j = 0; j < J; j++) {
105+
yAxis.append("text")
106+
.text(j + 1)
107+
.attr("x", xScale(0) - 5)
108+
.attr("y", yScale(j));
109+
}
110+
111+
var pieces = svg.append("g").attr("id", "pieces");
112+
for (var i = 0; i < I; i++) {
113+
for (var j = 0; j < J; j++) {
114+
pieces.append("circle")
115+
.attr("cx", xScale(i))
116+
.attr("cy", yScale(j))
117+
.attr("r", 10)
118+
.attr("id", "_" + String.fromCharCode(i + this.alphaOffset) + (j+1))
119+
.attr("stroke", "none")
120+
.attr("fill", "none");
121+
pieces.append("text")
122+
.attr("x", xScale(i))
123+
.attr("y", yScale(j))
124+
.attr("id", "__" + String.fromCharCode(i + this.alphaOffset) + (j+1));
125+
}
126+
}
127+
};
128+
129+
return Board;
130+
});

src/Kifu.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
*/
3+
4+
define(function(require, exports, module) {
5+
var SGFGrove = require("SGFGrove");
6+
7+
function Kifu() {
8+
this.meta = [];
9+
this.trunk = [];
10+
this.currentMove = -1;
11+
return this;
12+
}
13+
14+
Kifu.prototype.loadFromSGF = function(sgf) {
15+
var collection = SGFGrove.parse(sgf);
16+
var gameTree = collection[0];
17+
var trunk = gameTree[0];
18+
this.meta = trunk[0];
19+
this.trunk = trunk.slice(1);
20+
this.meta.NM = this.trunk.length;
21+
this.currentMove = 0;
22+
};
23+
24+
Kifu.prototype.translateCoords = function(ndx) {
25+
if (typeof(ndx) == "undefined") { ndx = this.kifu.currentMove; }
26+
var alphaOffset = "A".charCodeAt();
27+
var move = this.trunk[ndx];
28+
var side = Object.keys(move)[0];
29+
return [
30+
move[side][0].toUpperCase(), // char
31+
move[side][1].toUpperCase().charCodeAt() - alphaOffset + 1
32+
];
33+
};
34+
35+
Kifu.prototype.renderMeta = function(table) {
36+
var fieldMap = {
37+
"DT": "Date",
38+
"EV": "Event",
39+
"PB": "Black",
40+
"PW": "White",
41+
"RE": "Result",
42+
"TM": "Time Limit",
43+
"NM": "Number of Moves"
44+
};
45+
while (table.childElementCount > 0) {
46+
table.removeChild(table.children[0]);
47+
}
48+
var tbody = document.createElement("tbody");
49+
Object.keys(fieldMap).forEach(function(key) {
50+
var tr = document.createElement("tr");
51+
var tdl = document.createElement("td");
52+
var tdr = document.createElement("td");
53+
tdl.textContent = fieldMap[key] + ": ";
54+
tdl.setAttribute("class", "metaField");
55+
tdr.textContent = this.meta[key];
56+
tdr.setAttribute("class", "metaValue");
57+
tr.appendChild(tdl);
58+
tr.appendChild(tdr);
59+
tbody.appendChild(tr);
60+
}, this);
61+
table.appendChild(tbody);
62+
};
63+
64+
Kifu.prototype.renderHistory = function(table, rowAttrs) {
65+
if (typeof(rowAttrs) == "undefined") { rowAttrs = {}; }
66+
var tbody = table.querySelector("tbody");
67+
while (tbody.childElementCount > 0) {
68+
tbody.removeChild(tbody.children[0]);
69+
}
70+
this.trunk.forEach(function(move, ndx) {
71+
var coords = this.translateCoords(ndx);
72+
var tr = document.createElement("tr");
73+
var tdl = document.createElement("td");
74+
var tdr = document.createElement("td");
75+
Object.keys(rowAttrs).forEach(function(key) {
76+
tr.setAttribute(key, rowAttrs[key]);
77+
}, this);
78+
tdl.textContent = (ndx + 1);
79+
tdr.textContent = coords[0] + coords[1];
80+
tr.appendChild(tdl);
81+
tr.appendChild(tdr);
82+
tbody.appendChild(tr);
83+
}, this);
84+
};
85+
86+
return Kifu;
87+
});

0 commit comments

Comments
 (0)