Compare commits

..

9 Commits

16 changed files with 7 additions and 2040 deletions

View File

@ -131,9 +131,7 @@ fn parse_sequence<'a, E: nom::error::ParseError<&'a str>>(
println!("::: parse_sequence: {}", input); println!("::: parse_sequence: {}", input);
let (input, _) = multispace0(input)?; let (input, _) = multispace0(input)?;
let (input, nodes) = many1(parse_node)(input)?; let (input, nodes) = many1(parse_node)(input)?;
let (input, _) = multispace0(input)?;
let (input, sub_sequences) = many0(parse_tree)(input)?; let (input, sub_sequences) = many0(parse_tree)(input)?;
let (input, _) = multispace0(input)?;
Ok(( Ok((
input, input,
@ -159,7 +157,6 @@ fn parse_property<'a, E: nom::error::ParseError<&'a str>>(
let (input, _) = multispace0(input)?; let (input, _) = multispace0(input)?;
let (input, ident) = alpha1(input)?; let (input, ident) = alpha1(input)?;
let (input, values) = many1(parse_propval)(input)?; let (input, values) = many1(parse_propval)(input)?;
let (input, _) = multispace0(input)?;
let values = values let values = values
.into_iter() .into_iter()
@ -480,22 +477,4 @@ k<. Hard line breaks are all other linebreaks.",
.to_owned() .to_owned()
); );
} }
#[test]
fn it_parses_sgf_with_newline_in_sequence() {
let data = String::from(
"(;FF[4]C[root](;C[a];C[b](;C[c])(;C[d];C[e]
))(;C[f](;C[g];C[h];C[i])(;C[j])))",
);
parse_tree::<nom::error::VerboseError<&str>>(&data).unwrap();
}
#[test]
fn it_parses_sgf_with_newline_between_two_sequence_closings() {
let data = String::from(
"(;FF[4]C[root](;C[a];C[b](;C[c])(;C[d];C[e])
)(;C[f](;C[g];C[h];C[i])(;C[j])))",
);
parse_tree::<nom::error::VerboseError<&str>>(&data).unwrap();
}
} }

51
kifu/core/Cargo.lock generated
View File

@ -45,7 +45,6 @@ dependencies = [
"js-sys", "js-sys",
"num-integer", "num-integer",
"num-traits", "num-traits",
"time",
"wasm-bindgen", "wasm-bindgen",
"winapi", "winapi",
] ]
@ -110,15 +109,6 @@ dependencies = [
"syn 2.0.12", "syn 2.0.12",
] ]
[[package]]
name = "go-sgf"
version = "0.1.0"
dependencies = [
"chrono",
"nom",
"thiserror",
]
[[package]] [[package]]
name = "grid" name = "grid"
version = "0.9.0" version = "0.9.0"
@ -171,10 +161,8 @@ dependencies = [
name = "kifu-core" name = "kifu-core"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"go-sgf",
"grid", "grid",
"serde", "serde",
"serde_json",
"thiserror", "thiserror",
"typeshare", "typeshare",
] ]
@ -203,34 +191,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "no-std-compat" name = "no-std-compat"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.45"
@ -368,17 +334,6 @@ dependencies = [
"syn 2.0.12", "syn 2.0.12",
] ]
[[package]]
name = "time"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]] [[package]]
name = "typeshare" name = "typeshare"
version = "1.0.1" version = "1.0.1"
@ -413,12 +368,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.84" version = "0.2.84"

View File

@ -6,9 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
go-sgf = { path = "../../go-sgf" }
grid = { version = "0.9" } grid = { version = "0.9" }
serde_json = { version = "1" }
serde = { version = "1", features = [ "derive" ] } serde = { version = "1", features = [ "derive" ] }
thiserror = { version = "1" } thiserror = { version = "1" }
typeshare = { version = "1" } typeshare = { version = "1" }

View File

@ -1,432 +0,0 @@
(;FF[4]
CA[UTF-8]
GM[1]
GN[2019 Masters R7 B1]
PC[https://online-go.com/review/404377]
PB[Zhongfan Jian]
PW[Mark Lee]
BR[7d]
WR[7d]
TM[0]OT[0 none]
RE[B+R]
SZ[19]
KM[7.5]
RU[AGA]
C[
-- chat --
krnzmb: hi
FrostedNuke: hi
USGO1: Hello! As most of you know, this is the final round of the US Open Master's division at the US Go Congress between Mark Lee 7d (w) and Zhongfan Jian 7d (b)
]
;B[dp]
;W[pp]
;B[dd]
;W[pd]
;B[nc]
;W[fc]
;B[hc]C[
-- chat --
snakesss: h16
BHydden: close
]
;W[cc]
;B[dc]
;W[cd]
;B[de]
;W[db]C[
-- chat --
hardstone: Mark Lee is B?
hardstone: ok, W
]
;B[eb]
;W[cb]
;B[fb]
;W[cf]
;B[qf]
;W[pf]
;B[pg]
;W[of]
;B[qd]
;W[qc]
;B[qe]
;W[pb]C[
-- chat --
MeiGuoTang: crosstabs
]
;B[og]C[
-- chat --
MeiGuoTang: please
]
;W[md]
;B[qn]
;W[jc]C[
-- chat --
shipshape: https://www.usgo.org/tournaments/crosstab/band-matrix/187
snakesss: lol he played the only move i just checked on my bot and saw was a bad one
snakesss: feels good to have the same bad instinct as a pro
]
;B[nq]
;W[pn]
;B[pm]
;W[on]
;B[qp]
;W[gc]C[
-- chat --
hexahedron: tenuki from the lower right is very interesting
snakesss: "interesting" like "haylee
snakesss: 's interestings"?
redreoicy: First guess is to make a ladder breaker to play r7
Cyanriddle: h16 would be simple
]
;B[gd]
;W[fd]C[
-- chat --
hexahedron: so black resists the ladder
]
;B[gb]
;W[hd]C[
-- chat --
redreoicy: but, i thought white's intention was to follow up a few more moves than just g17 before playing r7
]
;B[id]
;W[ge]
;B[ic]
;W[qm]
;B[qo]
;W[pl]C[
-- chat --
redreoicy: ok g15 makes a lot more sense
USGO1: Sorry about that, table shook a bit as I placed G15
BHydden: if you're the pedantic type, you can click onto the wrong move 40 and then click the trashcan :)
]
;B[hf]
;W[om]
;B[df]
;W[cg]
;B[fg]
;W[oq]
;B[qr]
;W[pr]
;B[fq]
;W[pe]
;B[qi]
;W[ie]
;B[jd]
;W[he]
;B[mc]C[
-- chat --
USGO1: Zhongfan put that one down with no small amount of vigor
BHydden: this area is mine, don't at me
]
;W[hg]
;B[oc]
;W[pc]
;B[ld]
;W[if]
;B[jp]C[
-- chat --
hexahedron: white upper right right not having local live has got to feel annoying for white
BHydden: eh, he tenukid from an approach... it's to be expected, right?
]
;W[bp]
;B[cp]
;W[bo]
;B[bq]
;W[br]
;B[cq]
;W[cl]C[
-- chat --
hexahedron: it used to be okay,but black got to dig out the top area while white had to defend the center group
]
;B[dk]
;W[ck]
;B[dj]
;W[dn]
;B[cn]
;W[bn]
;B[dg]
;W[ho]
;B[iq]
;W[dh]
;B[ch]C[
-- chat --
BHydden: quiet in here
hexahedron: friday night, not surprising :)
BHydden: final round of USGC, who could have more important plans than this? :D
USGO1: I agree with BHydden:)
BHydden: ;)
USGO1: Mark has used more than half his time, now being at 42 minutes
xed_over: on this one move? :)
hexahedron: maybe white didn't expect this move by black
USGO1: I'm not sure about Zhongfan's time left, but he IS 2/3 of the way through a starbucks
USGO1: I'm now told by our fearless recording leader that Black has an hour and ten minutes left
]
;W[ei]
;B[bh]
;W[ce]
;B[fj]
;W[ej]
;B[ek]
;W[fi]
;B[di]
;W[eh]
;B[gi]
;W[gj]
;B[fk]
;W[gh]
;B[hi]
;W[fh]C[
-- chat --
樱桃花: what's popping
]
;B[bj]
;W[co]
;B[ec]
;W[hj]
;B[fn]
;W[aq]
;B[cr]
;W[bk]
;B[ii]
;W[ij]
;B[ji]
;W[jj]
;B[ki]
;W[eg]
;B[kj]
;W[hl]C[
-- chat --
Falchion: what did it say the % was at move 114?
hexahedron: around 95% for black
Falchion: wow, already that bad
hexahedron: keep in mind not to trust all these percents too much, we've seen in plenty of games at this tournament that it can swing quite a bit
hexahedron: bot is assuming superhuman-level tactics, in a sharp position it's very possible for one mistake to swing it all the way back to even
]
;B[dm]
;W[cm]
;B[jl]
;W[jm]
;B[km]
;W[jn]
;B[kn]
;W[il]
;B[jk]
;W[kl]
;B[kk]C[
-- chat --
Falchion: last few moves feel good for B
hexahedron: KG says 97% for B (white lives in the middle, but black got a lot of profit
hexahedron: )
hexahedron: and connects his own group on the left in the process
hexahedron: we'll see what happens though, the tactics are so complicated
]
;W[gn]
;B[en]
;W[dl]C[
-- chat --
Falchion: B would have to mess up pretty badly to throw such an advantage away though
hexahedron: after the last 3 moves KG is thinking the white group in the middle dies now
Falchion: ouch, that's even worse
hexahedron: it's not entirely confident though, territory map shows it as all blackish, but not completely
]
;B[fm]C[
-- chat --
Zhadow: what is KG?
]
;W[jo]C[
-- chat --
hexahedron: bot that is around LZ-ELFv2 strength, but with score estimation and territory prediction
]
;B[ko]
;W[hq]
;B[in]C[
-- chat --
hexahedron: oooh black's going for the kill!
Falchion: J5 here?
]
;W[io]
;B[gq]C[
-- chat --
hexahedron: G3 nice
Falchion: J4 now maybe?
hexahedron: no, J4 makes no eyeshape
hexahedron: all it would do is strengthen black and immediately kill any hope of black messing up
hexahedron: (the only point that J4 could help turn into an eye is H4, but notice how G3 and J3 already make H4 false)
hexahedron: do you see?
hexahedron: right, and that would help black
hexahedron: there's no ko
hexahedron: the only bit that remains not entirely clear to my lowly amateur reading is the L4 cut aji
hexahedron: but maybe I"m also missing some other variations
USGO1: The clock now tells us that Mark has only 10 minutes of main time remaining
]
(;W[fo]C[
-- chat --
Falchion: G5 then?
]
)(;W[ip]
;B[jq]
;W[gr]
;B[hr]
;W[ir]
;B[hp]
;W[hs]C[
-- chat --
Falchion: J4 would make B play at K3 probably?
Falchion: maybe it sets up a ko
]
)(;W[gp]
;B[fp]
;W[kp]C[
-- chat --
Falchion: hey, he played your L4 cut
]
;B[lp]C[
-- chat --
hexahedron: ooh maybe white does have something
]
;W[kq]
;B[lq]C[
-- chat --
Falchion: hm, not sure it works tho
]
;W[kr]C[
-- chat --
USGO1: Mark kept his finger on that stone for a long while before releaing and pressing the clock
]
;B[hr]C[
-- chat --
USGO1: Zhongfan is now down to an eighth of his coffee
dy_baduk: hmmr
dy_baduk: j2 might actually be reasonable
hexahedron: ko?
]
;W[ir]C[
-- chat --
Falchion: nice dy
hexahedron: I guess there might be a ko after all :)
Falchion: I think you found it
dy_baduk: lol
dy_baduk: it's cause I do a shit ton of tsumego
Falchion: wait, what about K2 next, does W still die?
]
(;B[jq]
;W[ip]
;B[hp]
;W[fl]
;B[go]C[B+r
-- chat --
Falchion: board is different tho
USGO1: W resigns
Falchion: ouch
hexahedron: congrats to black (zhongfan)
hexahedron: really nice play at the end
]
)(;B[jr]
;W[ip]
;B[is]
;W[jq]
;B[ir]
;W[lr]
;B[mr]
;W[lo]C[
-- chat --
hexahedron: @Falchion - something like this. From move 0: D4 Q4 D16 Q16 O17 F17 H17 C17 D17 C16 D15 D18 E18 C18 F18 C14 R14 Q14 Q13 P14 R16 R17 R15 Q18 P13 N16 R6 K17 O3 Q6 Q7 P6 R4 G17 G16 F16 G18 H16 J16 G15 J17 R7 R5 Q8 H14 P7 D14 C13 F13 P3 R2 Q2 F3 Q15 R11 J15 K16 H15 N17 H13 P17 Q17 M16 J14 K4 B4 C4 B5 B3 B2 C3 C8 D9 C9 D10 D6 C6 B6 D13 H5 J3 D12 C12 E11 B12 C15 F10 E10 E9 F11 D11 E12 G11 G10 F9 G12 H11 F12 B10 C5 E17 H10 F6 A3 C2 B9 J11 J10 K11 K10 L11 E13 L10 H8 D7 C7 K8 K7 L7 K6 L6 J8 K9 L8 L9 G6 E6 D8 F7 K5 L5 H3 J6 J5 G3 G4 F4 L4 M4 L3 M3 L2 H2 J2 K2 J4 J1 K3 J2 M2 N2 M5
Falchion: yeah
]
)))

View File

@ -1,499 +0,0 @@
(;FF[4]
CA[UTF-8]
GM[1]
GN[2019 Masters R7 B2]
PC[https://online-go.com/review/404376]
PB[Eric Lui]
PW[Nyu Eiko]
BR[1p]
WR[2p]
TM[0]OT[0 none]
RE[W+r]
SZ[19]
KM[7.5]
RU[AGA]
C[
-- chat --
dogbert: when will the game start?
USGO2: in approximately 15 minutes
USGO2: After the ceremonies the game should begin any minute now
USGO2: Putting phones into the designated bins
USGO2: TD Josh Lee yells out "2 minutes"
USGO2: Both players have sat, game should begin soon
]
;B[pd]
;W[dd]
;B[pq]
;W[dp]
;B[qk]
;W[nc]
;B[pf]
;W[qc]
;B[pc]
;W[pb]
;B[qd]
;W[rb]
;B[rc]
;W[qb]
;B[fq]C[
-- chat --
BHydden: wow lightning opening
]
;W[cn]
;B[lp]
;W[hq]
;B[fo]C[
-- chat --
mark5000: This is a traditional and well-studied opening pattern, if you excuse the 2016-era joseki in the upper left.
]
;W[jp]C[
-- chat --
BHydden: looks at upper left... sees lonely isolated 4-4 stone... yes, such joseki o.o
mark5000: Ha, which one is left again? ;)
mark5000: It's been a long day.
]
;B[dm]C[
-- chat --
BHydden: if you hold up both your hands, the left one can make an L between index and thumb with palm facing away from you ;)
]
;W[dn]
;B[em]
;W[en]C[
-- chat --
pyv: I thought you were referring to the fact that noone went 3-3 yet
pyv: as an old joseki
]
;B[fn]
;W[fm]C[
-- chat --
BHydden: i accept that it was a standard and well known pattern... but I'm still not used to pros putting stones on the board that quickly :P
BHydden: we had a move 8 3-3 so they can hold off a bit on the other one ;)
USGO2: Nyu dug into her purse and got out what appeared to be a piece of gum or a breathmint
BHydden: for herself or as a subtle insult to her opponent to throw Eric off his game?
]
;B[gm]
;W[fl]C[
-- chat --
USGO2: For herself as far as i can tell
]
;B[kn]
;W[hn]
;B[gn]
;W[jn]
;B[km]
;W[il]C[
-- chat --
Аlрhа - 1 5 2: Hmm, I wonder if saving f5 worth W extending f8.
]
;B[dr]
;W[cq]C[
-- chat --
Аlрhа - 1 5 2: Or can B live in the lower left somehow?
]
;B[im]C[
-- chat --
USGO2: Eric has almost played a move a few times now but always puts the stone back in the bowl. but finally committed to this one
USGO2: then steps out of the room
]
;W[hm]C[
-- chat --
BHydden: ominous
USGO2: Nyu's focus has completely unwavered meanwhile
USGO2: Eric has returned
]
;B[gl]
;W[fk]
;B[jm]
;W[hl]
;B[gk]
;W[fj]C[
-- chat --
unholysix1: white must feel pretty confident about living along the bottom
]
;B[gj]
;W[fi]C[
-- chat --
Аlрhа - 1 5 2: B f5 is not out of the woods yet tho...
unholysix1: pretty close to being out of them
]
;B[in]
;W[ho]C[
-- chat --
unholysix1: ohh neat
Аlрhа - 1 5 2: W can still harras that group to help save h5 if h5 can't live at the bottom.
]
;B[kq]C[
-- chat --
unholysix1: hmm... I thought b had to deend the f4 cut after white's move. guess not
]
;W[ij]
;B[jk]
;W[hj]
;B[gi]
(;W[fh]C[
-- chat --
Аlрhа - 1 5 2: I think f4 cut douesn't work because of W's h4 aji.
unholysix1: no i just misread it. b has a sequence to make it fail
]
;B[gh]C[
-- chat --
unholysix1: that one seems to work
unholysix1: white just relentlessly takes that 6 line territory. fun stuff
]
;W[ih]C[
-- chat --
USGO2: Eric has used 40 minutes so far. Deducting from the start of the game, that means Nyu has used maybe 10 or so minutes
USGO2: Can't see Nyu's time unless Eric checks it
]
;B[hg]C[
-- chat --
Аlрhа - 1 5 2: Looks like B is determined to kill h5 no matter the cost.
]
;W[ki]C[
-- chat --
unholysix1: whites like sorry, noly need one eye and now i've got stones to connect to
]
;B[cf]C[
-- chat --
Аlрhа - 1 5 2: Hmm.
]
;W[ce]
;B[df]C[
-- chat --
unholysix1: so cool. :-D
]
;W[gg]C[
-- chat --
Аlрhа - 1 5 2: B doesn't need to connect at h12 I think. He can kill f12 if he cuts.
]
(;B[hh]C[
-- chat --
unholysix1: c8 net. 6 libs w to 3 for b
]
;W[ee]C[
-- chat --
unholysix1: ok b cuts w extend im guessing you want b to e13? i play c8 net
unholysix1: doe
unholysix1: er done
]
;B[cj]C[
-- chat --
unholysix1: now hes using your plan haha
unholysix1: only net still works
Аlрhа - 1 5 2: He's not going for the kill tho.
unholysix1: hes trying to live
]
;W[bk]C[
-- chat --
unholysix1: thats most of whites points so far. its huge if he pulls it off
USGO2: Eric slips on his jacket. Despite it being almost 100F today its fairly ccomfortable in the strong players room
]
;B[bj]
;W[di]C[
-- chat --
Аlрhа - 1 5 2: d9?
unholysix1: And the heat is on black in this game! :-P
]
;B[ch]
;W[be]
;B[bf]C[
-- chat --
unholysix1: she still chewing that gum?
USGO2: I never saw a chewing motion so i assume it was a mint instead of gum
unholysix1: ooohhhh that explains a lot
USGO2: I think this is the longest she has spent on a move so far
unholysix1: this is exciting.
]
;W[gf]C[
-- chat --
unholysix1: wow. make a move and save those if you want. I'll just trap this string
]
;B[dh]
;W[jf]C[
-- chat --
unholysix1: !
]
;B[jh]
;W[ii]C[
-- chat --
Falchion: the B stick is contained and needs to find 2 eyes, right?
]
;B[hr]
;W[gp]
;B[gq]C[
-- chat --
unholysix1: thats the way it is
]
;W[fp]C[
-- chat --
unholysix1: he just traded the tail for the rest
aesalon: fat tail
unholysix1: for sure
]
;B[kh]
;W[lh]C[
-- chat --
USGO2: Nyu leaves the room
]
;B[lg]C[
-- chat --
USGO2: and returns
]
;W[kg]
;B[he]C[
-- chat --
USGO2: Eric dropped the stone onto the board but fortunately it fell into an empty area
unholysix1: This looks like making it worse to me.
]
;W[jg]
;B[hf]
;W[id]C[
-- chat --
S_Alexander: white feels good?
Falchion: ya, think so
Falchion: B is going to have to make a huge territory on the right side to even it up
]
;B[hd]C[
-- chat --
unholysix1: I mean what black's doing, it would work on me 100%
]
;W[ic]
;B[fg]
;W[ff]
;B[eg]
;W[dl]
;B[ec]
;W[dc]
;B[db]
;W[cb]C[
-- chat --
Nova Luna: ko. From move 0: Q16 D16 Q3 D4 R9 O17 Q14 R17 Q17 Q18 R16 S18 S17 R18 F3 C6 M4 H3 F5 K4 D7 D6 E7 E6 F6 F7 G7 F8 L6 H6 G6 K6 L7 J8 D2 C3 J7 H7 G8 F9 K7 H8 G9 F10 G10 F11 J6 H5 L3 J10 K9 H10 G11 F12 G12 J12 H13 L11 C14 C15 D14 G13 H12 E15 C10 B9 B10 D11 C12 B15 B14 G14 D12 K14 K12 J11 H2 G4 G3 F4 L12 M12 M13 L13 H15 K13 H14 J16 H16 J17 F13 F14 E13 D8 E17 D17 D18 C18
Zhadow: where
Zhadow: cant white G17 if black F18
Zhadow: ?
unholysix1: could he be thinking of e18 and just maing whte play a defensive move in the corner? he has a couple of forcing moves around the cut points?
USGO2: Eric has 10 minutes main time left. Nyu has approximately 50
mekriff 白金花: Anybody got a win rate?
]
;B[fe]
;W[ge]
;B[fd]
;W[ef]
;B[fb]
;W[eh]
;B[dg]
;W[gd]C[
-- chat --
USGO2: Given the info that Mark Lee lost on board 1, if Nyu wins this game she will very likely be the Masters winner
aesalon: Yeah
]
;B[gc]C[
-- chat --
aesalon: and it looks near impossible for W to lose
]
;W[bc]
;B[hc]
;W[bg]C[
-- chat --
USGO2: Nyu steps across the room to refill her cup of water. Theres many water coolers in this building which is great given the heat this week
unholysix1: so at this point leela says white is winning 90% and the black group is dead
Zhadow: which one, left side or the stick
unholysix1: left side although there are variations where the stick dies instead
]
;B[ae]C[
-- chat --
unholysix1: it also expects fighting to start soon with an invasion around the Q3 stone
]
;W[ad]
;B[bl]
;W[ck]
;B[cm]
;W[bm]C[
-- chat --
USGO2: Eric has entered byo yomi. 5 periods of 30 seconds
]
;B[bn]C[
-- chat --
unholysix1: wow now it wants black to pla d15, w e16 b c16 and white take the f16 stones. b lives on the side the string dies
aesalon: It's difficult to parse bot variations when it's so lopsided
]
;W[am]
;B[al]
;W[cl]
;B[an]
;W[bm]
;B[ak]
;W[el]C[W+Resign
-- chat --
USGO2: 4 periods left
USGO2: 3 periods left
USGO2: Eric shuts off the clock. White wins the game. Thanks for watching!
savanni.dgerinel: Thank you for transcribing!
S_Alexander: gg
]
)(;B[fg]
;W[gf]
;B[dk]C[
-- chat --
Аlрhа - 1 5 2: ?. From move 0: Q16 D16 Q3 D4 R9 O17 Q14 R17 Q17 Q18 R16 S18 S17 R18 F3 C6 M4 H3 F5 K4 D7 D6 E7 E6 F6 F7 G7 F8 L6 H6 G6 K6 L7 J8 D2 C3 J7 H7 G8 F9 K7 H8 G9 F10 G10 F11 J6 H5 L3 J10 K9 H10 G11 F12 G12 J12 H13 L11 C14 C15 D14 G13 F13 G14 D9
]
))(;W[fp]
;B[ep]
;W[gp]
;B[eo]
;W[eq]
;B[dq]C[
-- chat --
Аlрhа - 1 5 2: this one?. From move 0: Q16 D16 Q3 D4 R9 O17 Q14 R17 Q17 Q18 R16 S18 S17 R18 F3 C6 M4 H3 F5 K4 D7 D6 E7 E6 F6 F7 G7 F8 L6 H6 G6 K6 L7 J8 D2 C3 J7 H7 G8 F9 K7 H8 G9 F10 G10 F11 J6 H5 L3 J10 K9 H10 G11 F4 E4 G4 E5 E3 D3
]
))

View File

@ -1,395 +0,0 @@
(;FF[4]
CA[UTF-8]
GM[1]
GN[2019 Masters R7 B3]
PC[https://online-go.com/review/404375]
PB[Alan Huang]
PW[Yongfei Ge]
BR[7d]
WR[7d]
TM[0]OT[0 none]
RE[B+7.5]
SZ[19]
KM[7.5]
RU[AGA]
C[
-- chat --
USGO3: Welcome to Round 7 of the US Masters. This is the last round. This is table 3.
]
;B[pd]
;W[dc]
;B[qp]
;W[dq]
;B[np]
;W[nc]
;B[qf]
;W[pc]
;B[qc]
;W[qb]
;B[oc]
;W[pb]
;B[od]
;W[ob]
;B[nd]
;W[mc]
;B[ce]
;W[dh]
;B[co]
;W[cl]
;B[ep]
;W[dp]
;B[do]
;W[eo]
;B[eq]
;W[er]
;B[fr]
;W[dr]
;B[en]
;W[fo]
;B[gp]
;W[dn]
;B[cn]
;W[dm]
;B[gn]
;W[fn]
;B[fm]
;W[em]
;B[go]
;W[fl]
;B[gm]
;W[bp]
;B[pk]C[
-- chat --
redreoicy: Go Alan! I'm sure AI prefers black here :)
]
;W[lq]
;B[lp]
;W[kp]
;B[lo]
;W[nq]
;B[oq]
;W[mr]
;B[or]
;W[ko]
;B[ln]
;W[iq]
;B[kn]
;W[hr]
;B[dd]C[
-- chat --
USGO3: The game has been underway for about 30 minutes...B has used about 19 minutes.
]
;W[ec]
;B[cc]
;W[cb]
;B[bb]
;W[bc]
;B[bd]
;W[cd]
;B[kr]C[
-- chat --
redreoicy: Good part about that joseki in lower left is that it leaves so many easy threats
]
;W[kq]
;B[cc]
;W[qi]
;B[qj]
;W[oi]
;B[mi]
;W[qg]
;B[pf]
;W[rj]
;B[rk]
;W[rf]
;B[rh]
;W[pj]
;B[qk]
;W[rg]
;B[rd]
;W[ri]
;B[ph]C[
-- chat --
USGO3: About 1 hour into the game...B has used 39 minutes of time
]
;W[pg]
;B[oh]
;W[og]
;B[nh]
;W[qh]
;B[md]
;W[re]
;B[lc]
;W[rc]
;B[qd]
;W[sd]
;B[ac]
;W[hc]
;B[lb]
;W[mb]
;B[ma]
;W[nb]
;B[ke]
;W[pi]
;B[nk]
;W[nj]
;B[mj]C[
-- chat --
Falchion: B needs to play F4 at some point, no? It's forcing too
]
;W[gk]
;B[cj]C[
-- chat --
USGO3: 90 minutes in...B has used 52 minutes
]
;W[ci]
;B[dj]
;W[fi]
;B[bj]
;W[bk]C[
-- chat --
Falchion: is that B group just going to die? jumping in like that was pretty risky
]
;B[bh]
;W[gh]C[
-- chat --
Falchion: guess it lives, but low, and W wasn't reduced very much
]
;B[ek]
;W[el]
;B[hi]
;W[gj]
;B[ik]
;W[hh]
;B[ii]
;W[ih]
;B[ed]
;W[fd]C[
-- chat --
Zhadow: how much time does each player have left?
USGO3: B has 21 min
]
;B[ni]C[
-- chat --
USGO3: They have been playing 117 minutes
USGO3: I will let you do the math for W
Zhadow: thanks
]
;W[kg]
;B[ic]
;W[id]
;B[jc]
;W[hb]
;B[jr]
;W[gr]
;B[fs]
;W[io]
;B[jn]
;W[gq]
;B[fq]
;W[hp]
;B[fp]
;W[en]
;B[jo]
;W[jp]
;B[ir]
;W[gs]
;B[ho]
;W[in]
;B[im]
;W[is]
;B[fe]
;W[gd]
;B[db]
;W[eb]
;B[ca]
;W[jd]
;B[kd]
;W[jb]C[
-- chat --
USGO3: B has 10 minutes basic time left
]
;B[mf]
;W[sk]
;B[sl]
;W[sj]
;B[ql]
;W[bi]
;B[ai]
;W[ch]
;B[bg]
;W[ib]
;B[jh]
;W[jg]
;B[kh]
;W[ok]
;B[ol]
;W[oj]
;B[mk]
;W[nr]
;B[os]
;W[lg]
;B[ng]
;W[lh]
;B[li]
;W[ge]
;B[ff]
;W[df]
;B[cf]
;W[dg]
;B[fg]
;W[fh]
;B[de]
;W[je]
;B[ei]
;W[eh]
;B[rb]
;W[sc]
;B[se]
;W[sf]
;B[ra]
;W[sb]
;B[na]
;W[qa]
;B[ea]
;W[fb]
;B[kf]
;W[jf]C[
-- chat --
USGO3: B in byomi
]
;B[gf]
;W[hf]
;B[of]
;W[kc]
;B[hn]
;W[ns]
;B[mp]
;W[ls]
;B[ip]
;W[io]
;B[lr]
;W[mq]
;B[js]
;W[jq]
;B[hs]
;W[hq]
;B[cp]
;W[cq]
;B[ds]
;W[br]
;B[es]
;W[cs]
;B[kb]
;W[jc]
;B[hk]
;W[hj]
;B[ij]
;W[gl]
;B[hl]
;W[ak]
;B[aj]
;W[qe]
;B[ck]
;W[bl]
;B[gg]
;W[pe]
;B[oe]
;W[lf]
;B[le]
;W[fa]
;B[da]
;W[hg]
;B[oa]
;W[sa]
;B[cg]
;W[ja]
;B[la]
;W[is]
;B[in]
;W[ks]
;B[ip]
;W[rm]
;B[rl]
;W[io]
;B[bs]
;W[as]
;B[ip]
;W[pm]
;B[pl]
;W[io]
;B[ej]
;W[dl]
;B[ip]
;W[op]
;B[pq]
;W[io]
;B[ee]
;W[ip]
;B[ah]
;W[fj]
;B[mg]
;W[mh]
;B[ld]
;W[ka]
;B[dk]
;W[di]
;B[pa]
;W[eg]
;B[ef]
;W[fk]
;B[gi]
;W[]C[
-- chat --
USGO3: Counting
]
;B[]
;W[]C[B+7.5
-- chat --
USGO3: B wins
]
)

View File

@ -1,224 +0,0 @@
(;FF[4]GM[1]AP[gobandroid:0]SZ[19]GN[Kat vs. Savanni]DT[2022-10-05]PB[Kat]PW[Savanni]BR[10k]WR[10k]KM[6.5]RE[W+15.5]
;B[dp]
;W[pd]
;B[qp]
;W[cd]
;B[oq]
;W[fd]
;B[qf]
;W[qh]
(;B[pf]
)(;B[of]
;W[nd]
;B[mf]
;W[pk]
;B[ql]
;W[qk]
;B[cj]
;W[jp]
;B[hq]
;W[le]
;B[jc]
;W[lc]
;B[gc]
;W[fc]
;B[qd]
;W[qc]
;B[rd]
;W[rc]
;B[pe]
;W[od]
;B[ri]
;W[qi]
;B[rh]
;W[di]
;B[dl]
;W[ci]
;B[lp]
;W[jn]
;B[hn]
;W[cq]
;B[dq]
;W[cp]
;B[co]
;W[bo]
;B[cn]
;W[bn]
;B[cm]
;W[dr]
;B[er]
;W[cr]
;B[fq]
;W[ln]
;B[nm]
;W[nk]
;B[ol]
;W[ok]
;B[lk]
;W[ng]
;B[nf]
;W[mj]
;B[ml]
;W[pl]
;B[qm]
;W[om]
;B[nn]
;W[nl]
;B[mm]
;W[kl]
;B[hk]
;W[ho]
;B[io]
;W[in]
;B[ip]
;W[hm]
;B[gn]
;W[jo]
;B[jq]
;W[mp]
;B[np]
;W[mo]
;B[no]
;W[kq]
;B[jr]
;W[mq]
;B[hf]
;W[ff]
;B[lf]
;W[jd]
;B[ic]
;W[jf]
;B[jk]
;W[kk]
;B[fk]
;W[kr]
;B[nr]
;W[mr]
;B[lj]
;W[mi]
;B[li]
;W[jh]
;B[ji]
;W[lg]
;B[hl]
;W[dj]
;B[ck]
;W[fj]
;B[jl]
;W[ll]
;B[mk]
;W[jm]
;B[gm]
;W[gh]
;B[hi]
;W[hd]
;B[hc]
;W[hh]
;B[fi]
;W[fh]
;B[ei]
;W[eh]
;B[ej]
;W[ek]
;B[gj]
;W[gi]
;B[fj]
;W[dk]
;B[el]
;W[pg]
;B[dh]
;W[ch]
;B[dg]
;W[cf]
;B[mg]
;W[og]
;B[kb]
;W[lb]
;B[fb]
;W[eb]
;B[gb]
;W[ec]
;B[ig]
;W[ih]
;B[kf]
;W[kg]
;B[je]
;W[ie]
;B[ke]
;W[if]
;B[id]
;W[gd]
;B[ld]
;W[md]
;B[me]
;W[pm]
;B[qn]
;W[rj]
;B[rg]
;W[rl]
;B[rm]
;W[bj]
;B[bk]
;W[cg]
;B[bi]
;W[bh]
;B[aj]
;W[mh]
;B[kc]
;W[kj]
;B[pn]
;W[on]
;B[oo]
;W[jj]
;B[ij]
;W[ki]
;B[lh]
;W[ii]
;B[hj]
;W[lm]
;B[im]
;W[ns]
;B[os]
;W[ms]
;B[bm]
;W[bp]
;B[la]
;W[ma]
;B[ka]
;W[mb]
;B[sk]
;W[sl]
;B[sj]
;W[rk]
;B[si]
;W[sm]
;B[sn]
;W[js]
;B[ir]
;W[is]
;B[hs]
;W[ks]
;B[ea]
;W[da]
;B[fa]
;W[db]
;B[sc]
;W[sb]
;B[sd]
;W[rb]
;B[ds]
;W[cs]
;B[es]
;W[nq]
;B[or]
;W[am]
;B[al]
;W[an]
;B[kh]
;W[jg]
;B[ah]
;W[ag]
;B[ai]
;W[qg]
;B[pf]
))

View File

@ -1,179 +0,0 @@
(;FF[4]GM[1]AP[gobandroid:0]SZ[19]DT[2023-04-19]PB[Steve]PW[Savanni]KM[6.5]
;B[dd]
;W[pp]
;B[pd]
;W[dp]
;B[qn]
;W[qo]
;B[pn]
;W[np]
;B[qj]
;W[cf]
;B[fc]
;W[cd]
;B[cc]
;W[bc]
;B[cb]
;W[bb]
;B[ce]
;W[bd]
;B[de]
;W[be]
;B[df]
;W[cg]
;B[ck]
;W[dg]
;B[cn]
;W[co]
;B[bn]
;W[en]
;B[ek]
;W[ef]
;B[ee]
;W[db]
;B[dc]
;W[ca]
;B[eb]
;W[da]
;B[ge]
;W[ff]
;B[fe]
;W[dj]
;B[bo]
;W[bp]
;B[di]
;W[dk]
;B[cj]
;W[dl]
;B[cl]
;W[ei]
;B[ci]
;W[eh]
;B[ej]
;W[el]
;B[fm]
;W[gn]
;B[do]
;W[cp]
;B[dn]
;W[eo]
;B[em]
;W[fl]
;B[gk]
;W[gl]
;B[gm]
;W[hm]
;B[fn]
;W[fo]
;B[dm]
;W[hl]
;B[go]
;W[hn]
;B[gp]
;W[ep]
;B[gq]
;W[ip]
;B[er]
;W[dr]
;B[iq]
;W[jq]
;B[ir]
;W[jr]
;B[hp]
;W[jp]
;B[eq]
;W[dq]
;B[fp]
;W[br]
;B[ds]
;W[cs]
;B[es]
;W[nn]
;B[nj]
;W[nc]
;B[lc]
;W[qc]
;B[pc]
;W[qd]
;B[qe]
;W[pb]
;B[ob]
;W[qb]
;B[oc]
;W[nb]
;B[oa]
;W[pe]
;B[oe]
;W[pf]
;B[of]
;W[pg]
;B[re]
;W[sc]
;B[nd]
;W[kd]
;B[kc]
;W[jd]
;B[ic]
;W[md]
;B[mc]
;W[ne]
;B[od]
;W[me]
;B[og]
;W[oh]
;B[ph]
;W[qh]
;B[pi]
;W[rf]
;B[qg]
;W[qf]
;B[rg]
;W[rd]
;B[sf]
;W[mg]
;B[nh]
;W[om]
;B[ql]
;W[mh]
;B[mi]
;W[li]
;B[lj]
;W[kj]
;B[lh]
;W[ki]
;B[lg]
;W[ng]
;B[oi]
;W[lk]
;B[mf]
;W[nf]
;B[lf]
;W[ld]
;B[jg]
;W[hf]
;B[ie]
;W[id]
;B[hd]
;W[jc]
;B[jb]
;W[ib]
;B[hb]
;W[kb]
;B[lb]
;W[ja]
;B[na]
;W[hc]
;B[gc]
;W[he]
;B[gd]
;W[ic]
;B[ha]
;W[if]
;B[je]
;W[ih]
;B[ke]
;W[kh]
;B[le]
;W[kg]
;B[ia]
)

View File

@ -1,7 +1,6 @@
use crate::{ use crate::{
types::{AppState, GameState, Player, Rank}, types::{AppState, GameState, Player, Rank},
ui::{new_game, playing_field, NewGameView, PlayingFieldView}, ui::{new_game, playing_field, NewGameView, PlayingFieldView},
Config,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -65,16 +64,14 @@ pub enum CoreResponse {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CoreApp { pub struct CoreApp {
config: Config,
state: Arc<RwLock<AppState>>, state: Arc<RwLock<AppState>>,
} }
impl CoreApp { impl CoreApp {
pub fn new(config_path: std::path::PathBuf) -> Self { pub fn new() -> Self {
let config = Config::from_path(config_path).expect("configuration to open");
let state = Arc::new(RwLock::new(AppState::new())); let state = Arc::new(RwLock::new(AppState::new()));
Self { config, state } Self { state }
} }
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse { pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {

View File

@ -1,139 +0,0 @@
use crate::types::Player;
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fs::File,
io::{ErrorKind, Read},
path::PathBuf,
};
use thiserror::Error;
/*
pub trait ConfigOption {
type Value;
}
pub struct DatabasePath(PathBuf);
impl ConfigOption for DatabasePath {
type Value = PathBuf;
}
impl ConfigOption for Player {
type Value = Player;
}
pub trait Config {
// fn set_option(option: ConfigOption);
fn get_option<N, C: ConfigOption>(name: Name) -> C<Name = Name>
}
*/
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
enum OptionNames {
DatabasePath,
Me,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ConfigOption {
DatabasePath(DatabasePath),
Me(Me),
}
#[derive(Debug, Error)]
pub enum ConfigReadError {
#[error("Cannot read the configuration file: {0}")]
CannotRead(std::io::Error),
#[error("Cannot open the configuration file for reading: {0}")]
CannotOpen(std::io::Error),
#[error("Invalid json data found in the configurationfile: {0}")]
InvalidJSON(serde_json::Error),
}
#[derive(Clone, Debug)]
pub struct Config {
config_path: PathBuf,
values: HashMap<OptionNames, ConfigOption>,
}
impl Config {
pub fn new(config_path: PathBuf) -> Self {
Self {
config_path,
values: HashMap::new(),
}
}
pub fn from_path(config_path: PathBuf) -> Result<Self, ConfigReadError> {
let mut settings = config_path.clone();
settings.push("config");
match File::open(settings) {
Ok(mut file) => {
let mut buf = String::new();
file.read_to_string(&mut buf)
.map_err(|err| ConfigReadError::CannotRead(err))?;
let values = serde_json::from_str(buf.as_ref())
.map_err(|err| ConfigReadError::InvalidJSON(err))?;
Ok(Self {
config_path,
values,
})
}
Err(io_err) => {
match io_err.kind() {
ErrorKind::NotFound => {
/* create the path and an empty file */
Ok(Self {
config_path,
values: HashMap::new(),
})
}
_ => Err(ConfigReadError::CannotOpen(io_err)),
}
}
}
}
fn set(&mut self, val: ConfigOption) {
let _ = match val {
ConfigOption::DatabasePath(_) => self.values.insert(OptionNames::DatabasePath, val),
ConfigOption::Me(_) => self.values.insert(OptionNames::Me, val),
};
}
fn get<'a, T>(&'a self) -> T
where
T: From<&'a Self>,
{
self.into()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DatabasePath(PathBuf);
impl From<&Config> for DatabasePath {
fn from(config: &Config) -> Self {
match config.values.get(&OptionNames::DatabasePath) {
Some(ConfigOption::DatabasePath(path)) => path.clone(),
_ => DatabasePath(config.config_path.clone()),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Me(Player);
impl From<&Config> for Option<Me> {
fn from(config: &Config) -> Self {
config
.values
.get(&OptionNames::Me)
.and_then(|val| match val {
ConfigOption::Me(me) => Some(me.clone()),
_ => None,
})
}
}

View File

@ -1,77 +0,0 @@
use std::{ffi::OsStr, io::Read, os::unix::ffi::OsStrExt, path::PathBuf};
use go_sgf::go::{parse_sgf, GameTree, GameType};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("Database permission denied")]
PermissionDenied,
#[error("An IO error occurred: {0}")]
IOError(std::io::Error),
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Error::IOError(err)
}
}
pub struct Database {
path: PathBuf,
games: Vec<GameTree>,
}
impl Database {
pub fn open_path(path: PathBuf) -> Result<Database, Error> {
let mut games: Vec<GameTree> = Vec::new();
let extension = PathBuf::from("sgf").into_os_string();
let path_iter = std::fs::read_dir(path.clone())?;
for entry in path_iter {
match entry {
Ok(entry) => {
if entry.path().extension() == Some(&extension) {
let mut buffer = String::new();
std::fs::File::open(entry.path())
.unwrap()
.read_to_string(&mut buffer)
.unwrap();
let sgf = parse_sgf(&buffer).unwrap();
games.extend(sgf);
}
}
Err(err) => println!("failed entry: {:?}", err),
}
}
Ok(Database { path, games })
}
pub fn all_games(&self) -> impl Iterator<Item = &GameTree> {
self.games.iter()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn it_reads_empty_database() {
let db = Database::open_path(PathBuf::from("fixtures/empty_database/"))
.expect("database to open");
assert_eq!(db.all_games().count(), 0);
}
#[test]
fn it_reads_five_games_from_database() {
let db =
Database::open_path(PathBuf::from("fixtures/five_games/")).expect("database to open");
assert_eq!(db.all_games().count(), 5);
for game in db.all_games() {
assert_eq!(game.game_type, GameType::Go);
}
}
}

View File

@ -3,14 +3,9 @@ pub use api::{
CoreApp, CoreRequest, CoreResponse, CreateGameRequest, HotseatPlayerRequest, PlayerInfoRequest, CoreApp, CoreRequest, CoreResponse, CreateGameRequest, HotseatPlayerRequest, PlayerInfoRequest,
}; };
mod board;
pub use board::*;
mod config;
pub use config::*;
mod database;
mod types; mod types;
pub use types::{BoardError, Color, Rank, Size}; pub use types::{BoardError, Color, Rank, Size};
pub mod ui; pub mod ui;
mod board;
pub use board::*;

View File

@ -91,7 +91,7 @@ impl From<Rank> for String {
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Debug)]
pub struct Player { pub struct Player {
pub name: String, pub name: String,
pub rank: Option<Rank>, pub rank: Option<Rank>,

1
kifu/gtk/Cargo.lock generated
View File

@ -787,7 +787,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"grid", "grid",
"serde", "serde",
"serde_json",
"thiserror", "thiserror",
"typeshare", "typeshare",
] ]

View File

@ -44,12 +44,7 @@ fn main() {
.unwrap(), .unwrap(),
); );
let user_home = std::env::var("HOME").expect("the user's home directory isn't set"); let core = CoreApp::new();
let mut config_path = std::path::PathBuf::from(user_home);
config_path.push(".config");
config_path.push("kifu");
let core = CoreApp::new(config_path);
let core_handle = runtime.spawn({ let core_handle = runtime.spawn({
let core = core.clone(); let core = core.clone();