Skip to content

Commit 2666aea

Browse files
authored
More point quality of life improvements. (#201)
* More point quality of life improvements. 1. Add a point key that can be used in Maps. Add a test. 2. Move SGF logic to a separate file 3. Add an equals method for points. Fixes: #196
1 parent 619664f commit 2666aea

File tree

3 files changed

+91
-42
lines changed

3 files changed

+91
-42
lines changed

core/point/point.go

+24-42
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,6 @@ type Point struct {
1212
y int64
1313
}
1414

15-
// pointToSgfMap is a translation reference between int64 Point
16-
// and string SGF-Point (rune) values
17-
var pointToSgfMap = map[int64]rune{
18-
0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g',
19-
7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n',
20-
14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u',
21-
21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B',
22-
28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I',
23-
35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P',
24-
42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W',
25-
49: 'X', 50: 'Y', 51: 'Z',
26-
}
27-
28-
// sgfToPointMap is a translation reference between string SGF-Point
29-
// (rune) values and int64 Point values
30-
var sgfToPointMap = func(m map[int64]rune) map[rune]int64 {
31-
out := make(map[rune]int64)
32-
for key, val := range m {
33-
out[val] = key
34-
}
35-
return out
36-
}(pointToSgfMap)
37-
3815
// New creates a new immutable Point.
3916
func New(x, y int64) *Point {
4017
return &Point{
@@ -52,29 +29,34 @@ func (pt *Point) Y() int64 { return pt.y }
5229
// ToSGF converts a pointer-type (immutable) *Point
5330
// to an SGF Point (two letter string).
5431
func (pt *Point) ToSGF() (string, error) {
55-
if pt.X() < 0 || pt.X() > 51 || pt.Y() < 0 || pt.Y() > 51 {
56-
return "", fmt.Errorf("error converting point to SGF-point; points must be between 0 and 51 inclusive. found %v", pt.String())
57-
}
58-
return string(pointToSgfMap[pt.X()]) + string(pointToSgfMap[pt.Y()]), nil
32+
return toSGF(pt)
33+
}
34+
35+
// Equals returns whether this point is equal to another point.
36+
func (pt *Point) Equals(other *Point) bool {
37+
return pt.X() == other.X() && pt.Y() == other.Y()
5938
}
6039

6140
// String converts to string representation of a Point.
62-
func (pt Point) String() string {
41+
func (pt *Point) String() string {
6342
return fmt.Sprintf("{%d,%d}", pt.x, pt.y)
6443
}
6544

66-
// NewFromSGF converts an SGF point (two letter string) to a Point.
67-
func NewFromSGF(sgfPt string) (*Point, error) {
68-
if sgfPt == "" || len(sgfPt) != 2 {
69-
return nil, fmt.Errorf("sgf point must be non-empty and two letter char, but was %s", sgfPt)
70-
}
71-
intX, ok := sgfToPointMap[rune(sgfPt[0])]
72-
if !ok {
73-
return nil, fmt.Errorf("could not convert coordinate for x-value of sgf point %s; only a-zA-Z (minus i/I) are allowed", sgfPt)
74-
}
75-
intY, ok := sgfToPointMap[rune(sgfPt[1])]
76-
if !ok {
77-
return nil, fmt.Errorf("could not convert coordinate for y-value of sgf point %s; only a-zA-Z (minus i/I) are allowed", sgfPt)
78-
}
79-
return New(intX, intY), nil
45+
// Key is a convenience helper to convert this point to a key-struct.
46+
func (pt *Point) Key() Key {
47+
return Key{X: pt.X(), Y: pt.Y()}
48+
}
49+
50+
// Key is a point-struct that is used for keys in maps. As such, it's intended
51+
// to be used like the following:
52+
//
53+
// Key{X:12, Y:15}
54+
type Key struct {
55+
X int64
56+
Y int64
57+
}
58+
59+
// Point converts a point-Key back to a point.
60+
func (k Key) Point() *Point {
61+
return New(k.X, k.Y)
8062
}

core/point/point_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,20 @@ func TestSGFToPointTranslate(t *testing.T) {
140140
}
141141
})
142142
}
143+
}
144+
145+
func TestKey(t *testing.T) {
146+
pt := New(12, 15)
147+
148+
key := pt.Key()
149+
exp := Key{X: 12, Y: 15}
143150

151+
if key != exp {
152+
t.Errorf("error converting point to key: got %v, but expected %v", key, exp)
153+
}
154+
155+
back := exp.Point()
156+
if !pt.Equals(back) {
157+
t.Errorf("error converting key to point: got %v, but expected %v", back, pt)
158+
}
144159
}

core/point/sgf.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package point
2+
3+
import "fmt"
4+
5+
// TODO(kashomon): This whole file needs to be moved to core/sgf
6+
7+
// pointToSgfMap is a translation reference between int64 Point
8+
// and string SGF-Point (rune) values
9+
var pointToSgfMap = map[int64]rune{
10+
0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g',
11+
7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n',
12+
14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u',
13+
21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B',
14+
28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I',
15+
35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P',
16+
42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W',
17+
49: 'X', 50: 'Y', 51: 'Z',
18+
}
19+
20+
// sgfToPointMap is a translation reference between string SGF-Point
21+
// (rune) values and int64 Point values
22+
var sgfToPointMap = func(m map[int64]rune) map[rune]int64 {
23+
out := make(map[rune]int64)
24+
for key, val := range m {
25+
out[val] = key
26+
}
27+
return out
28+
}(pointToSgfMap)
29+
30+
// NewFromSGF converts an SGF point (two letter string) to a Point.
31+
func NewFromSGF(sgfPt string) (*Point, error) {
32+
if sgfPt == "" || len(sgfPt) != 2 {
33+
return nil, fmt.Errorf("sgf point must be non-empty and two letter char, but was %s", sgfPt)
34+
}
35+
intX, ok := sgfToPointMap[rune(sgfPt[0])]
36+
if !ok {
37+
return nil, fmt.Errorf("could not convert coordinate for x-value of sgf point %s; only a-zA-Z (minus i/I) are allowed", sgfPt)
38+
}
39+
intY, ok := sgfToPointMap[rune(sgfPt[1])]
40+
if !ok {
41+
return nil, fmt.Errorf("could not convert coordinate for y-value of sgf point %s; only a-zA-Z (minus i/I) are allowed", sgfPt)
42+
}
43+
return New(intX, intY), nil
44+
}
45+
46+
// toSGF converts a point to an SGF coordinate.
47+
func toSGF(pt *Point) (string, error) {
48+
if pt.X() < 0 || pt.X() > 51 || pt.Y() < 0 || pt.Y() > 51 {
49+
return "", fmt.Errorf("error converting point to SGF-point; points must be between 0 and 51 inclusive. found %v", pt.String())
50+
}
51+
return string(pointToSgfMap[pt.X()]) + string(pointToSgfMap[pt.Y()]), nil
52+
}

0 commit comments

Comments
 (0)