From b2c6d80ff5c1f53b3df69ec7ed5c6b6289275e0c Mon Sep 17 00:00:00 2001 From: Josh Hoak Date: Tue, 22 Mar 2016 08:42:51 -0600 Subject: [PATCH] Add support for parsing FF3 by ignoring lower case chars is props. fixes: https://github.com/Kashomon/glift/issues/125 related to: https://github.com/Kashomon/glift/issues/101 --- src/compiled/glift.js | 40 ++-- src/compiled/glift_combined.js | 47 ++--- src/htmltests/AjaxProblemTester.html | 1 - src/htmltests/BaseWidgetTest.html | 1 - src/htmltests/BboxFinder.html | 1 - src/htmltests/BoardEditorTester.html | 1 - src/htmltests/ExampleTester.html | 1 - src/htmltests/GameFigureTester.html | 1 - src/htmltests/GameViewerTester.html | 1 - src/htmltests/IconBarTester.html | 1 - src/htmltests/KogosTester.html | 1 - src/htmltests/MarksTester.html | 1 - src/htmltests/MoveNumberCircleTester.html | 1 - src/htmltests/PerfTester.html | 1 - src/htmltests/PositionTester.html | 1 - src/htmltests/ProblemServerTester.html | 1 - src/htmltests/ProblemTester.html | 1 - src/htmltests/QunitTest.html | 1 - src/htmltests/TextOnlyTester.html | 1 - src/htmltests/ThemeTester.html | 1 - src/htmltests/TygemGameTester.html | 1 - src/parse/pandanet.js | 11 -- src/parse/pandanet_test.js | 2 +- src/parse/parse.js | 28 ++- src/parse/parse_test.js | 15 +- src/parse/sgf_parser.js | 6 + src/parse/tygem.js | 1 + src/testdata/PandanetFF3Example.sgf | 211 ++++++++++++++++++++++ 28 files changed, 285 insertions(+), 95 deletions(-) delete mode 100644 src/parse/pandanet.js create mode 100644 src/testdata/PandanetFF3Example.sgf diff --git a/src/compiled/glift.js b/src/compiled/glift.js index 07a84ac8..40d35ccf 100644 --- a/src/compiled/glift.js +++ b/src/compiled/glift.js @@ -80,9 +80,9 @@ glift.marked.Parser.prototype.parse=function(a){this.inline=new glift.marked.Inl glift.marked.Parser.prototype.tok=function(){switch(this.token.type){case "space":return"";case "hr":return this.renderer.hr();case "heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case "code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case "table":var a="",b="",c,d,e,f;e="";for(c=0;cc?e=a*c:dc-1&&(f=c-1);var e=b.tl.intPt.y(),g=a.pageY;a.changedTouches&&a.changedTouches[0]&&(g=a.changedTouches[0].pageY);a=Math.floor((g-d.top)/b.spacing)+e;ac-1&&(a=c-1);c=glift.util.point(f,a);this.rotation!=glift.enums.rotations.NO_ROTATION&&(c=c.antirotate(this.boardPoints.numIntersections,this.rotation));return c}};glift.displays.board.lines=function(a,b,c,d){if(null===c)throw Error("boardPoints null: Gui Environment obj not initialized");var e=glift.displays.svg,f=e.group().setId(b.lineGroup());a.append(f);a=c.data();for(var g=0,h=a.length;g=f?1E7:f;e=0>=e?0:e;for(var p=0,u=0;uh?h/b[u].width():k/b[u].height(),v=new glift.displays.gui.Transform(r),r=b[u].scale(r);l.push(v);m.push(r);p+=n(r,g);uf&&(e=f,u=(v-e*(l.length-1))/2);d=a.left()+d;a=a.top()+c;"h"===g?d+=u:a+=u;c=[];for(u=0;u=f?1E7:f;e=0>=e?0:e;for(var q=0,r=0;rh?h/b[r].width():k/b[r].height(),v=new glift.displays.gui.Transform(u),u=b[r].scale(u);l.push(v);m.push(u);q+=n(u,g);rf&&(e=f,r=(v-e*(l.length-1))/2);d=a.left()+d;a=a.top()+c;"h"===g?d+=r:a+=r;c=[];for(r=0;rb.height()/b.width()?e/b.width():f/b.width();b=b.scale(g);d=a.left()+d;b.width()b;b++)a.push(0);glift.rules.treepath.storedToEnd_=a;return glift.rules.treepath.storedToEnd_},findNextMovesPath:function(a,b,c,d){b=b||a.treepathToHere();d=!1===d?!1:!0;a=a.getTreeFromRoot(b);c=c||1E3;b=[];for(var e=a.onMainline(),f=0;a.node().getParent()&&fd;d++)b[d+1]=!0;for(d=0;26>d;d++){var e=""+String.fromCharCode(65+d);c[e]=!0}for(var e=[a.CIRCLE,a.LABEL,a.SQUARE,a.TRIANGLE,a.XMARK],f=/^[A-Z]$/,g=/^\d*$/,d=0;d -1) { - if (str.indexOf('PANDANET') > -1) { - ttype = parseType.PANDANET; - } else { - ttype = parseType.SGF; - } + ttype = parseType.SGF; } else if (filename.indexOf('.gib') > -1) { ttype = parseType.TYGEM; } @@ -11141,6 +11145,10 @@ glift.parse = { */ fromString: function(str, opt_ttype) { var ttype = opt_ttype || glift.parse.parseType.SGF; + if (ttype === glift.parse.parseType.PANDANET) { + // PANDANET type is now equivalent to SGF. + ttype = glift.parse.parseType.SGF; + } var methodName = glift.enums.toCamelCase(ttype); var func = glift.parse[methodName]; var movetree = func(str); @@ -11148,18 +11156,6 @@ glift.parse = { } }; -/** - * Parse a pandanet SGF. Pandanet SGFs, are the same as normal SGFs except that - * they contain invalid SGF properties. - */ -// TODO(kashomon): Delete and fold into SGF parsing. this is really a special -// case of FF3, which should be supported by Glift. -glift.parse.pandanet = function(string) { - var replaceRegex = /CoPyright\[[^\]]*\]/; - var repl = string.replace(replaceRegex, ''); - return glift.parse.sgf(repl); -}; - /** * Metadata Start and End tags allow us to insert metadata directly, as * JSON, into SGF comments. It will not be display by glift (although it @@ -11189,6 +11185,7 @@ glift.parse.sgfMetadataProperty = 'GC'; * * @param {string} sgfString * @return {!glift.rules.MoveTree} + * @package */ glift.parse.sgf = function(sgfString) { var states = { @@ -11217,6 +11214,7 @@ glift.parse.sgf = function(sgfString) { var wsRegex = /\s|\n/; var propRegex = /[A-Z]/; + var oldStyleProp = /[a-z]/; var curstate = states.BEGINNING_BEFORE_PAREN; var movetree = glift.rules.movetree.getInstance(); @@ -11311,6 +11309,9 @@ glift.parse.sgf = function(sgfString) { charBuffer.push(curchar); // In the SGF Specification, SGF properties can be of arbitrary // lengths, even though all standard SGF properties are 1-2 chars. + } else if (oldStyleProp.test(curchar)) { + // Do nothing. This is an FF1 - FF3 style property. For + // compatibility, we just ignore it and move on. } else if (curchar === syn.LBRACE) { curProp = flushCharBuffer(); if (glift.rules.prop[curProp] === undefined) { @@ -11401,6 +11402,7 @@ glift.parse.sgf = function(sgfString) { * @param {string} curchar * @param {string} message * @param {boolean} isWarning + * @package */ glift.parse.sgfParseError = function(lineNum, colNum, curchar, message, isWarning) { var header = 'SGF Parsing ' + (isWarning ? 'Warning' : 'Error'); @@ -11421,6 +11423,7 @@ glift.parse.sgfParseError = function(lineNum, colNum, curchar, message, isWarnin * * @param {string} gibString * @retutrn {!glift.rules.MoveTree} + * @package */ glift.parse.tygem = function(gibString) { var states = { diff --git a/src/htmltests/AjaxProblemTester.html b/src/htmltests/AjaxProblemTester.html index 3dfb3a76..eaee6160 100644 --- a/src/htmltests/AjaxProblemTester.html +++ b/src/htmltests/AjaxProblemTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/BaseWidgetTest.html b/src/htmltests/BaseWidgetTest.html index 318dddb7..b63b83a2 100644 --- a/src/htmltests/BaseWidgetTest.html +++ b/src/htmltests/BaseWidgetTest.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/BboxFinder.html b/src/htmltests/BboxFinder.html index 9088d75c..d8501ec7 100644 --- a/src/htmltests/BboxFinder.html +++ b/src/htmltests/BboxFinder.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/BoardEditorTester.html b/src/htmltests/BoardEditorTester.html index 97b4ac3b..595f3952 100644 --- a/src/htmltests/BoardEditorTester.html +++ b/src/htmltests/BoardEditorTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/ExampleTester.html b/src/htmltests/ExampleTester.html index 15939653..c9321bf4 100644 --- a/src/htmltests/ExampleTester.html +++ b/src/htmltests/ExampleTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/GameFigureTester.html b/src/htmltests/GameFigureTester.html index e3b41f78..dde6790b 100644 --- a/src/htmltests/GameFigureTester.html +++ b/src/htmltests/GameFigureTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/GameViewerTester.html b/src/htmltests/GameViewerTester.html index aaede176..b6d36086 100644 --- a/src/htmltests/GameViewerTester.html +++ b/src/htmltests/GameViewerTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/IconBarTester.html b/src/htmltests/IconBarTester.html index ea4b9edf..173d9e9e 100644 --- a/src/htmltests/IconBarTester.html +++ b/src/htmltests/IconBarTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/KogosTester.html b/src/htmltests/KogosTester.html index d4b3bdb5..34e9ab9c 100644 --- a/src/htmltests/KogosTester.html +++ b/src/htmltests/KogosTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/MarksTester.html b/src/htmltests/MarksTester.html index d2c06c01..e29bec6c 100644 --- a/src/htmltests/MarksTester.html +++ b/src/htmltests/MarksTester.html @@ -102,7 +102,6 @@ - diff --git a/src/htmltests/MoveNumberCircleTester.html b/src/htmltests/MoveNumberCircleTester.html index 1531fef1..80db9fd3 100644 --- a/src/htmltests/MoveNumberCircleTester.html +++ b/src/htmltests/MoveNumberCircleTester.html @@ -102,7 +102,6 @@ - diff --git a/src/htmltests/PerfTester.html b/src/htmltests/PerfTester.html index c25c7467..993bfcdd 100644 --- a/src/htmltests/PerfTester.html +++ b/src/htmltests/PerfTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/PositionTester.html b/src/htmltests/PositionTester.html index 3afa7bff..af0ec044 100644 --- a/src/htmltests/PositionTester.html +++ b/src/htmltests/PositionTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/ProblemServerTester.html b/src/htmltests/ProblemServerTester.html index fcbe1451..e491d82b 100644 --- a/src/htmltests/ProblemServerTester.html +++ b/src/htmltests/ProblemServerTester.html @@ -102,7 +102,6 @@ - diff --git a/src/htmltests/ProblemTester.html b/src/htmltests/ProblemTester.html index 08c16daf..fe2f141b 100644 --- a/src/htmltests/ProblemTester.html +++ b/src/htmltests/ProblemTester.html @@ -102,7 +102,6 @@ - diff --git a/src/htmltests/QunitTest.html b/src/htmltests/QunitTest.html index 831babf5..5194fec7 100644 --- a/src/htmltests/QunitTest.html +++ b/src/htmltests/QunitTest.html @@ -123,7 +123,6 @@ - diff --git a/src/htmltests/TextOnlyTester.html b/src/htmltests/TextOnlyTester.html index 2cf89e41..42b7a188 100644 --- a/src/htmltests/TextOnlyTester.html +++ b/src/htmltests/TextOnlyTester.html @@ -102,7 +102,6 @@ - diff --git a/src/htmltests/ThemeTester.html b/src/htmltests/ThemeTester.html index 09dd8fc7..c07d0cec 100644 --- a/src/htmltests/ThemeTester.html +++ b/src/htmltests/ThemeTester.html @@ -103,7 +103,6 @@ - diff --git a/src/htmltests/TygemGameTester.html b/src/htmltests/TygemGameTester.html index 8b8dac15..77c338f4 100644 --- a/src/htmltests/TygemGameTester.html +++ b/src/htmltests/TygemGameTester.html @@ -103,7 +103,6 @@ - diff --git a/src/parse/pandanet.js b/src/parse/pandanet.js deleted file mode 100644 index 47cc9ed1..00000000 --- a/src/parse/pandanet.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Parse a pandanet SGF. Pandanet SGFs, are the same as normal SGFs except that - * they contain invalid SGF properties. - */ -// TODO(kashomon): Delete and fold into SGF parsing. this is really a special -// case of FF3, which should be supported by Glift. -glift.parse.pandanet = function(string) { - var replaceRegex = /CoPyright\[[^\]]*\]/; - var repl = string.replace(replaceRegex, ''); - return glift.parse.sgf(repl); -}; diff --git a/src/parse/pandanet_test.js b/src/parse/pandanet_test.js index 400da1a6..f7a89930 100644 --- a/src/parse/pandanet_test.js +++ b/src/parse/pandanet_test.js @@ -49,7 +49,7 @@ // Patch in a testing logger. glift.util.logz = testLogger; - var f = glift.parse.pandanet(testfile); + var f = glift.parse.fromString(testfile, glift.parse.parseType.PANDANET); ok(f); f.moveDown(); deepEqual(f.properties().getOneValue('B'), 'qd'); diff --git a/src/parse/parse.js b/src/parse/parse.js index b73313a9..ecbb8f68 100644 --- a/src/parse/parse.js +++ b/src/parse/parse.js @@ -1,7 +1,7 @@ goog.provide('glift.parse'); /** - * Glift parsing + * Glift parsing for strings. */ glift.parse = { /** @@ -9,13 +9,21 @@ glift.parse = { * @enum {string} */ parseType: { - /** FF4 Parse Type */ + /** + * FF1-FF4 Parse Type. + */ SGF: 'SGF', + /** Tygem .gib files. */ TYGEM: 'TYGEM', - /** - * Really, this is FF3. - * TODO(kashomon): Support FF3 as first class citizen + + /** + * DEPRECATED. + * + * This was created when I didn't understand the destinction between the + * various FF versions. + * + * Prefer SGF. */ PANDANET: 'PANDANET' }, @@ -31,11 +39,7 @@ glift.parse = { var parseType = glift.parse.parseType; var ttype = parseType.SGF; if (filename.indexOf('.sgf') > -1) { - if (str.indexOf('PANDANET') > -1) { - ttype = parseType.PANDANET; - } else { - ttype = parseType.SGF; - } + ttype = parseType.SGF; } else if (filename.indexOf('.gib') > -1) { ttype = parseType.TYGEM; } @@ -51,6 +55,10 @@ glift.parse = { */ fromString: function(str, opt_ttype) { var ttype = opt_ttype || glift.parse.parseType.SGF; + if (ttype === glift.parse.parseType.PANDANET) { + // PANDANET type is now equivalent to SGF. + ttype = glift.parse.parseType.SGF; + } var methodName = glift.enums.toCamelCase(ttype); var func = glift.parse[methodName]; var movetree = func(str); diff --git a/src/parse/parse_test.js b/src/parse/parse_test.js index 2c5bd596..5a41900d 100644 --- a/src/parse/parse_test.js +++ b/src/parse/parse_test.js @@ -5,18 +5,9 @@ var sgfs = testdata.sgfs test('fromFileName', function() { - var oldFromString = glift.parse.fromString; - glift.parse.fromString = function(str, ttype) { - return ttype; - }; - - deepEqual(fromFileName('z', 'foo.sgf'), parseType.SGF); - deepEqual(fromFileName('z', 'foo.gib'), parseType.TYGEM); - deepEqual(fromFileName('PANDANET', 'foo.sgf'), parseType.PANDANET); - deepEqual(fromFileName('PANDANET', 'foo.gib'), parseType.TYGEM); - deepEqual(fromFileName('z', 'foo.zed'), parseType.SGF); - - glift.parse.fromString = oldFromString; + ok(fromFileName('(;GB[1])', 'foo.sgf'), parseType.SGF); + ok(fromFileName('(;GB[1]CoPyright[PANDANET])', 'foo.sgf'), parseType.SGF); + ok(fromFileName('STO 0 6 1 2 14 ', 'foo.gib')); }); test('from string: SGF, escaped comment', function() { diff --git a/src/parse/sgf_parser.js b/src/parse/sgf_parser.js index 703f9163..76a6471f 100644 --- a/src/parse/sgf_parser.js +++ b/src/parse/sgf_parser.js @@ -27,6 +27,7 @@ glift.parse.sgfMetadataProperty = 'GC'; * * @param {string} sgfString * @return {!glift.rules.MoveTree} + * @package */ glift.parse.sgf = function(sgfString) { var states = { @@ -55,6 +56,7 @@ glift.parse.sgf = function(sgfString) { var wsRegex = /\s|\n/; var propRegex = /[A-Z]/; + var oldStyleProp = /[a-z]/; var curstate = states.BEGINNING_BEFORE_PAREN; var movetree = glift.rules.movetree.getInstance(); @@ -149,6 +151,9 @@ glift.parse.sgf = function(sgfString) { charBuffer.push(curchar); // In the SGF Specification, SGF properties can be of arbitrary // lengths, even though all standard SGF properties are 1-2 chars. + } else if (oldStyleProp.test(curchar)) { + // Do nothing. This is an FF1 - FF3 style property. For + // compatibility, we just ignore it and move on. } else if (curchar === syn.LBRACE) { curProp = flushCharBuffer(); if (glift.rules.prop[curProp] === undefined) { @@ -239,6 +244,7 @@ glift.parse.sgf = function(sgfString) { * @param {string} curchar * @param {string} message * @param {boolean} isWarning + * @package */ glift.parse.sgfParseError = function(lineNum, colNum, curchar, message, isWarning) { var header = 'SGF Parsing ' + (isWarning ? 'Warning' : 'Error'); diff --git a/src/parse/tygem.js b/src/parse/tygem.js index 69b93d75..f33e8a4f 100644 --- a/src/parse/tygem.js +++ b/src/parse/tygem.js @@ -6,6 +6,7 @@ * * @param {string} gibString * @retutrn {!glift.rules.MoveTree} + * @package */ glift.parse.tygem = function(gibString) { var states = { diff --git a/src/testdata/PandanetFF3Example.sgf b/src/testdata/PandanetFF3Example.sgf new file mode 100644 index 00000000..7b41158d --- /dev/null +++ b/src/testdata/PandanetFF3Example.sgf @@ -0,0 +1,211 @@ +(; +GM[1]EV[Internet Go Server game: Namii vs drakula95] +US[Brought to you by IGS PANDANET] +CoPyright[ + Copyright (c) PANDANET Inc. 2014 + Permission to reproduce this game is given, provided proper credit is given. + No warrantee, implied or explicit, is understood. + Use of this game is an understanding and agreement of this notice. +] +GN[Namii-drakula95(B) IGS]RE[B+Resign] +PW[Namii]WR[5d?]NW[33] +PB[drakula95]BR[5d?]NB[33] +PC[IGS: igs.joyjoy.net 6969]DT[2014-11-05] +SZ[19]TM[3600]KM[6.500000]LT[] +RR[Normal] +C[ + Namii 5d?: 143 Have a nice game + drakula95 5d?: 143 have a nice game +] +;B[qd]BL[3587] +;W[dc]WL[3582] +;B[pp]BL[3570] +;W[dq]WL[3549] +;B[lc]BL[3547] +;W[qn]WL[3401] +;B[qk]BL[3527] +;W[nq]WL[3323] +;B[pn]BL[3524] +;W[qq]WL[3322] +;B[qo]BL[3519] +;W[pq]WL[3319] +;B[ce]BL[3466]C[ + gogeo 17k?: Hi + gogeo 17k?: color of what? + Oni 12k?: Namii white +] +;W[dh]WL[3138] +;B[co]BL[3327] +;W[ep]WL[2977] +;B[dm]BL[3204] +;W[de]WL[2619] +;B[df]BL[3168] +;W[ee]WL[2618] +;B[cd]BL[3166] +;W[cc]WL[2618] +;B[ef]BL[3162] +;W[ff]WL[2615] +;B[eg]BL[3078] +;W[ck]WL[2515] +;B[cl]BL[2710] +;W[dk]WL[2513] +;B[bq]BL[2709] +;W[bg]WL[2512] +;B[cg]BL[2658] +;W[bf]WL[2509]C[ + Oni 12k?: game also in http://online-go.com/demo/37741 +] +;B[cf]BL[2542] +;W[ch]WL[2507] +;B[fg]BL[2504]C[ + gogeo 17k?: thanks Namii +] +;W[gg]WL[2264] +;B[gh]BL[2460] +;W[gf]WL[2262] +;B[fi]BL[2458] +;W[ig]WL[2243] +;B[ic]BL[2323]C[ + drakula95 5d?: 129 sorry +] +;W[ij]WL[1819] +;B[gk]BL[2252] +;W[hl]WL[1805]C[ + Namii 5d?: 129 hm? + Namii 5d?: 129 ah +] +;B[fe]BL[1943] +;W[fc]WL[1789] +;B[ih]BL[1882] +;W[jh]WL[1787] +;B[ii]BL[1880] +;W[ji]WL[1787] +;B[fd]BL[1858] +;W[ec]WL[1765] +;B[jg]BL[1853] +;W[if]WL[1764] +;B[hd]BL[1792] +;W[hj]WL[1753] +;B[hh]BL[1692] +;W[qm]WL[1545] +;B[pm]BL[1498] +;W[ro]WL[1543] +;B[gc]BL[1386] +;W[pl]WL[1521] +;B[bi]BL[1344] +;W[bl]WL[1451] +;B[bh]BL[1244] +;W[cm]WL[1397] +;B[kg]BL[1185] +;W[lh]WL[1374] +;B[hp]BL[1028] +;W[jp]WL[1285] +;B[fo]BL[968] +;W[cn]WL[1011] +;B[do]BL[906] +;W[eo]WL[1009] +;B[dn]BL[904] +;W[en]WL[1009] +;B[dl]BL[887] +;W[bo]WL[900] +;B[bp]BL[759] +;W[fm]WL[541] +;B[bn]BL[492] +;W[lg]WL[527] +;B[kf]BL[486] +;W[lf]WL[525] +;B[ke]BL[485] +;W[lj]WL[520] +;B[jq]BL[360] +;W[kq]WL[511] +;B[iq]BL[251] +;W[kp]WL[456] +;B[fp]BL[224] +;W[fk]WL[438] +;B[ek]BL[206] +;W[fq]WL[372] +;B[gq]BL[200] +;W[fr]WL[370] +;B[hr]BL[133] +;W[go]WL[290] +;B[gn]BL[85] +;W[fn]WL[288] +;B[gp]BL[82] +;W[hn]WL[257] +;B[jr]BL[36] +;W[qf]WL[93] +;B[qh]BL[593] +;W[pd]WL[58] +;B[qc]BL[500] +;W[qe]WL[39] +;B[ql]BL[466] +;W[pk]WL[24] +;B[pj]BL[424] +;W[oj]WL[22] +;B[rp]BL[408] +;W[qp]WL[588] +;B[rn]BL[406] +;W[po]WL[584] +;B[rm]BL[405] +;W[qo]WL[583] +;B[pi]BL[349] +;W[pc]WL[573] +;B[pb]BL[328] +;W[ob]WL[572] +;B[qb]BL[283] +;W[nc]WL[562] +;B[rd]BL[281] +;W[bc]WL[520] +;B[be]BL[271] +;W[sn]WL[346] +;B[nj]BL[219] +;W[qj]WL[310] +;B[rj]BL[179] +;W[oi]WL[309] +;B[ok]BL[178] +;W[ol]WL[309] +;B[nk]BL[178] +;W[nl]WL[308] +;B[ml]BL[147] +;W[on]WL[297] +;B[pe]BL[80] +;W[oh]WL[169] +;B[oe]BL[72] +;W[le]WL[158] +;B[nd]BL[33] +;W[kd]WL[153] +;B[je]BL[32] +;W[mc]WL[132] +;B[oc]BL[25] +;W[jd]WL[94] +;B[ie]BL[23] +;W[lb]WL[93] +;B[ho]BL[19] +;W[gm]WL[81] +;B[fl]BL[6] +;W[kr]WL[53] +;B[js]BL[547] +;W[ip]WL[44] +;B[gr]BL[542] +;W[io]WL[31] +;B[pg]BL[464] +;W[og]WL[29] +;B[of]BL[458] +;W[rl]WL[15] +;B[rk]BL[454] +;W[sm]WL[514] +;B[kc]BL[389] +;W[jc]WL[512] +;B[kb]BL[387] +;W[jb]WL[511] +;B[mb]BL[375]; + +OS[ajeczka][AriSan][baldur][betterlife][BU2014] +[Crates][Ergo2012][Gardan][gisel88][gogeo] +[GoSuGo][GOvernor][hegethus][Hipcio][Iceape] +[JeffChang][Juippi][kare][kyusama][maek] +[mayeck][mdcl][nekocat][Nilatarion][ojisanshac] +[Oni][pempu][prodi][puerhista][RUBENDARIO] +[Sadiker][sakugo][siskin][Taksimies][Tantares] + +)