app.golfthesky.round
Schema Diff
+57 -2
Compatibility Analysis
Breaking Changes Detected
4 breaking changes, 14 non-breaking changes.
Breaking Changes (4)
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "app.golfthesky.round#player", src: "app.golfthesky.round#player", tgt: "app.golfthesky.round#player.did", kind: "prop", name: Some("did") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "app.golfthesky.round#player", src: "app.golfthesky.round#player", tgt: "app.golfthesky.round#player.handle", kind: "prop", name: Some("handle") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "app.golfthesky.round#player", src: "app.golfthesky.round#player", tgt: "app.golfthesky.round#player.holes", kind: "prop", name: Some("holes") }
- ConstraintTightened ConstraintTightened { vertex_id: "app.golfthesky.round#hole.holeId", sort: "knownValues", old_value: "[\"opening-drive\",\"dogleg\",\"sky-ramp\"]", new_value: "[\"opening-drive\",\"dogleg\",\"sky-ramp\",\"slick-slope\",\"bunker-alley\",\"island-hop\",\"first-light\",\"sticky-situation\",\"ice-cave\",\"archipelago\",\"clockwork\",\"mill-race\",\"skyhook\",\"paddle-alley\",\"crater\"]" }
Non-Breaking Changes (14)
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round#player" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round#player.did" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round#player.handle" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round#player.holes" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round#player.holes:items" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round:body.players" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round:body.players:items" }
- AddedVertex AddedVertex { vertex_id: "app.golfthesky.round:body.target" }
- AddedEdge AddedEdge { src: "app.golfthesky.round#player.holes", tgt: "app.golfthesky.round#player.holes:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "app.golfthesky.round#player.holes:items", tgt: "app.golfthesky.round#hole", kind: "ref", name: None }
- AddedEdge AddedEdge { src: "app.golfthesky.round:body", tgt: "app.golfthesky.round:body.players", kind: "prop", name: Some("players") }
- AddedEdge AddedEdge { src: "app.golfthesky.round:body", tgt: "app.golfthesky.round:body.target", kind: "prop", name: Some("target") }
- AddedEdge AddedEdge { src: "app.golfthesky.round:body.players", tgt: "app.golfthesky.round:body.players:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "app.golfthesky.round:body.players:items", tgt: "app.golfthesky.round#player", kind: "ref", name: None }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "app.golfthesky.round#player" }AddedVertex { vertex_id: "app.golfthesky.round#player.did" }AddedVertex { vertex_id: "app.golfthesky.round#player.handle" }AddedVertex { vertex_id: "app.golfthesky.round#player.holes" }AddedVertex { vertex_id: "app.golfthesky.round#player.holes:items" }AddedVertex { vertex_id: "app.golfthesky.round:body.players" }AddedVertex { vertex_id: "app.golfthesky.round:body.players:items" }AddedVertex { vertex_id: "app.golfthesky.round:body.target" }
Constraint Changes
- ConstraintTightened ConstraintTightened { vertex_id: "app.golfthesky.round#hole.holeId", sort: "knownValues", old_value: "[\"opening-drive\",\"dogleg\",\"sky-ramp\"]", new_value: "[\"opening-drive\",\"dogleg\",\"sky-ramp\",\"slick-slope\",\"bunker-alley\",\"island-hop\",\"first-light\",\"sticky-situation\",\"ice-cave\",\"archipelago\",\"clockwork\",\"mill-race\",\"skyhook\",\"paddle-alley\",\"crater\"]" }
Additional Notes
- Breaking: RequiredEdgeAdded { vertex_id: "app.golfthesky.round#player", src: "app.golfthesky.round#player", tgt: "app.golfthesky.round#player.did", kind: "prop", name: Some("did") }
- Breaking: RequiredEdgeAdded { vertex_id: "app.golfthesky.round#player", src: "app.golfthesky.round#player", tgt: "app.golfthesky.round#player.handle", kind: "prop", name: Some("handle") }
- Breaking: RequiredEdgeAdded { vertex_id: "app.golfthesky.round#player", src: "app.golfthesky.round#player", tgt: "app.golfthesky.round#player.holes", kind: "prop", name: Some("holes") }
- Non-breaking: AddedEdge { src: "app.golfthesky.round#player.holes", tgt: "app.golfthesky.round#player.holes:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "app.golfthesky.round#player.holes:items", tgt: "app.golfthesky.round#hole", kind: "ref", name: None }
- Non-breaking: AddedEdge { src: "app.golfthesky.round:body", tgt: "app.golfthesky.round:body.players", kind: "prop", name: Some("players") }
- Non-breaking: AddedEdge { src: "app.golfthesky.round:body", tgt: "app.golfthesky.round:body.target", kind: "prop", name: Some("target") }
- Non-breaking: AddedEdge { src: "app.golfthesky.round:body.players", tgt: "app.golfthesky.round:body.players:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "app.golfthesky.round:body.players:items", tgt: "app.golfthesky.round#player", kind: "ref", name: None }
1
1
{
2
2
"$type": "com.atproto.lexicon.schema",
3
3
"defs": {
4
4
"hole": {
5
5
"properties": {
6
6
"holeId": {
7
7
"description": "Permanent identity of the hole within the course.",
8
8
"knownValues": [
9
9
"opening-drive",
10
10
"dogleg",
11
-
"sky-ramp"
11
+
"sky-ramp",
12
+
"slick-slope",
13
+
"bunker-alley",
14
+
"island-hop",
15
+
"first-light",
16
+
"sticky-situation",
17
+
"ice-cave",
18
+
"archipelago",
19
+
"clockwork",
20
+
"mill-race",
21
+
"skyhook",
22
+
"paddle-alley",
23
+
"crater"
12
24
],
13
25
"maxLength": 64,
14
26
"type": "string"
15
27
},
16
28
"shots": {
17
-
"description": "The whole hole as the only input the game takes. Comma-separated `<dtick>.<yaw>.<pitch>.<power>` entries: dtick is 120 Hz ticks since the previous shot, yaw is milliradians (0–6283), pitch whole degrees, power 1–100. Example: `360.1571.24.80,540.1600.2.30`.",
29
+
"description": "The whole hole as the only input the game takes. Comma-separated `<dtick>.<angle>.<mod>.<power>` entries: dtick is 120 Hz ticks since the previous entry, angle is milliradians counter-clockwise from +x (0–6283), mod is the ball type applied to that swing (0 none, 1 sticky, 2 super, 3 nitro, 4 air brakes, 5 sniper), power 1–100. An entry with power 0 is an event, not a swing: mod 4 is an Air Brakes tap, mod 5 a Mulligan. Power-ups cost energy; a verifier recomputes energy from the clock (starts at 4, +1 every 360 ticks, max 10; costs sticky 4, super 3, nitro 4, brakes 5, mulligan 6, sniper 6) and refuses a log that overspends. Example: `360.785.0.80,540.0.4.0`.",
18
30
"maxLength": 8000,
19
31
"type": "string"
20
32
},
21
33
"strokes": {
22
34
"description": "Advisory stroke count, including out-of-bounds penalties.",
23
35
"minimum": 0,
24
36
"type": "integer"
25
37
},
26
38
"ticks": {
27
39
"description": "Advisory: the tick the ball dropped. Absent if the hole was never finished.",
28
40
"minimum": 1,
29
41
"type": "integer"
30
42
}
31
43
},
32
44
"required": [
33
45
"holeId",
34
46
"shots",
35
47
"strokes"
36
48
],
37
49
"type": "object"
38
50
},
39
51
"main": {
40
52
"description": "One Golf the Sky round, published by the player into their own repo. The record stores every shot rather than a score: the game's ball physics are deterministic, so re-simulating the shots reproduces the round exactly. Owning the record is the identity proof, and replaying it is the score proof — strokes and ticks in this record are advisory and never trusted by a leaderboard.",
41
53
"key": "tid",
42
54
"record": {
43
55
"properties": {
44
56
"courseId": {
45
57
"description": "Permanent identity of the course played. Append-only: ids are never reordered, renamed, or reused.",
46
58
"knownValues": [
47
59
"skyline-links"
48
60
],
49
61
"maxLength": 64,
50
62
"type": "string"
51
63
},
52
64
"createdAt": {
53
65
"format": "datetime",
54
66
"type": "string"
55
67
},
56
68
"field": {
57
69
"description": "How many players were in that live round.",
58
70
"minimum": 1,
59
71
"type": "integer"
60
72
},
61
73
"holes": {
62
74
"items": {
63
75
"ref": "#hole",
64
76
"type": "ref"
65
77
},
66
78
"maxLength": 18,
67
79
"type": "array"
68
80
},
69
81
"mode": {
70
82
"description": "solo: against local bots. live: against other players on a synced clock — the only mode in which placing means anything.",
71
83
"knownValues": [
72
84
"solo",
73
85
"live"
74
86
],
75
87
"type": "string"
76
88
},
77
89
"placing": {
78
90
"description": "Advisory finishing position in a live round, 1 = won.",
79
91
"minimum": 1,
80
92
"type": "integer"
81
93
},
94
+
"players": {
95
+
"description": "Everyone else who played this round, each with their own shot logs, so a replay of this one record shows the whole field. Bots carry a did of the form bot:N. Advisory, like placing: only the owner's own holes are theirs to prove.",
96
+
"items": {
97
+
"ref": "#player",
98
+
"type": "ref"
99
+
},
100
+
"maxLength": 7,
101
+
"type": "array"
102
+
},
82
103
"simVersion": {
83
104
"description": "Which physics produced these shots. A verifier must replay under the matching version or refuse the round.",
84
105
"minimum": 1,
85
106
"type": "integer"
107
+
},
108
+
"target": {
109
+
"description": "The pills (hole wins) the round was played to.",
110
+
"maximum": 9,
111
+
"minimum": 1,
112
+
"type": "integer"
86
113
}
87
114
},
88
115
"required": [
89
116
"courseId",
90
117
"simVersion",
91
118
"holes",
92
119
"createdAt"
93
120
],
94
121
"type": "object"
95
122
},
96
123
"type": "record"
124
+
},
125
+
"player": {
126
+
"properties": {
127
+
"did": {
128
+
"description": "Their DID, or bot:N for a local bot.",
129
+
"maxLength": 300,
130
+
"type": "string"
131
+
},
132
+
"handle": {
133
+
"description": "Their handle when the round was played (advisory).",
134
+
"maxLength": 100,
135
+
"type": "string"
136
+
},
137
+
"holes": {
138
+
"items": {
139
+
"ref": "#hole",
140
+
"type": "ref"
141
+
},
142
+
"maxLength": 18,
143
+
"type": "array"
144
+
}
145
+
},
146
+
"required": [
147
+
"did",
148
+
"handle",
149
+
"holes"
150
+
],
151
+
"type": "object"
97
152
}
98
153
},
99
154
"id": "app.golfthesky.round",
100
155
"lexicon": 1
101
156
}