Skip to content

Commit a51442e

Browse files
committed
Modularizes schemas for improved maintainability
Refactors the monolithic schema into separate definitions for each activity and shared elements, clarifying references and enabling simpler schema updates. Updates the validation logic to handle the new modular structure more effectively.
1 parent ef2c973 commit a51442e

File tree

8 files changed

+597
-889
lines changed

8 files changed

+597
-889
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.trackman.com/app-scripting/1-0-0/activity-performance-center.schema.json",
4+
"title": "Performance Center Activity",
5+
"$defs": {
6+
"PerformanceCenterScriptedSetupTarget": {
7+
"type": "object",
8+
"additionalProperties": false,
9+
"properties": {
10+
"nodeType": { "const": "PerformanceCenterScriptedSetupTarget" },
11+
"targetId": { "type": "string" },
12+
"distance": { "type": "number", "minimum": 0 }
13+
},
14+
"required": ["nodeType", "targetId", "distance"]
15+
},
16+
"PerformanceCenterScriptedSetupUsingTarget": {
17+
"type": "object",
18+
"additionalProperties": false,
19+
"properties": {
20+
"nodeType": { "const": "PerformanceCenterScriptedSetupUsingTarget" },
21+
"target": { "$ref": "#/$defs/PerformanceCenterScriptedSetupTarget" },
22+
"club": { "type": "string", "default": "Drv" }
23+
},
24+
"required": ["nodeType", "target"]
25+
},
26+
"PerformanceCenterScriptedSetupUsingDistance": {
27+
"type": "object",
28+
"additionalProperties": false,
29+
"properties": {
30+
"nodeType": { "const": "PerformanceCenterScriptedSetupUsingDistance" },
31+
"distance": { "type": "number", "minimum": 0 },
32+
"club": { "type": "string", "default": "Drv" }
33+
},
34+
"required": ["nodeType", "distance"]
35+
},
36+
"PerformanceCenterScriptedUI": {
37+
"type": "object",
38+
"additionalProperties": false,
39+
"properties": {
40+
"nodeType": { "const": "PerformanceCenterScriptedUI" },
41+
"perHoleMode": { "type": "boolean", "default": false },
42+
"activeDataTiles": { "type": "array", "items": { "$ref": "shared.schema.json#/$defs/ParameterName" }, "default": [] },
43+
"holeSelector": { "$ref": "shared.schema.json#/$defs/ParameterName" }
44+
},
45+
"required": ["nodeType"]
46+
},
47+
"PerformanceCenterScriptedLogic": {
48+
"type": "object",
49+
"additionalProperties": false,
50+
"properties": {
51+
"nodeType": { "const": "PerformanceCenterScriptedLogic" },
52+
"setup": { "oneOf": [ { "$ref": "#/$defs/PerformanceCenterScriptedSetupUsingTarget" }, { "$ref": "#/$defs/PerformanceCenterScriptedSetupUsingDistance" } ] },
53+
"successCondition": { "$ref": "shared.schema.json#/$defs/ConditionClause" },
54+
"failCondition": { "$ref": "shared.schema.json#/$defs/ConditionClause" }
55+
},
56+
"required": ["nodeType", "setup", "successCondition"]
57+
},
58+
"PerformanceCenterScriptedStep": {
59+
"type": "object",
60+
"additionalProperties": false,
61+
"properties": {
62+
"nodeType": { "const": "PerformanceCenterScriptedStep" },
63+
"id": { "$ref": "shared.schema.json#/$defs/IdString" },
64+
"introMessage": { "$ref": "shared.schema.json#/$defs/Message" },
65+
"successMessage": { "$ref": "shared.schema.json#/$defs/Message" },
66+
"failMessage": { "$ref": "shared.schema.json#/$defs/Message" },
67+
"logic": { "$ref": "#/$defs/PerformanceCenterScriptedLogic" },
68+
"ui": { "$ref": "#/$defs/PerformanceCenterScriptedUI" }
69+
},
70+
"required": ["nodeType", "id", "introMessage", "successMessage", "failMessage", "logic", "ui"]
71+
},
72+
"PerformanceCenterScriptedActivity": {
73+
"$anchor": "Activity",
74+
"type": "object",
75+
"additionalProperties": false,
76+
"properties": {
77+
"nodeType": { "const": "PerformanceCenterScriptedActivity" },
78+
"id": { "$ref": "shared.schema.json#/$defs/IdString" },
79+
"introMessage": { "$ref": "shared.schema.json#/$defs/Message" },
80+
"endMessage": { "$ref": "shared.schema.json#/$defs/Message" },
81+
"steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/PerformanceCenterScriptedStep" } }
82+
},
83+
"required": ["nodeType", "id", "introMessage", "endMessage", "steps"]
84+
}
85+
}
86+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.trackman.com/app-scripting/1-0-0/activity-range-analysis.json",
4+
"title": "Range Analysis Activity",
5+
"$defs": {
6+
"RangeAnalysisScriptedConditions": {
7+
"type": "object",
8+
"description": "Success/fail condition for Range Analysis steps. Counts shots that pass the per-shot clauses (if provided).",
9+
"additionalProperties": false,
10+
"properties": {
11+
"nodeType": { "const": "RangeAnalysisScriptedConditions", "description": "Discriminator. Must be exactly this value." },
12+
"shots": { "type": "integer", "minimum": 1, "description": "Threshold count." },
13+
"conditionType": { "$ref": "shared.schema.json#/$defs/ConditionType" },
14+
"conditions": { "type": "array", "minItems": 0, "items": { "$ref": "shared.schema.json#/$defs/ConditionClause" }, "default": [] }
15+
},
16+
"required": ["nodeType", "shots"]
17+
},
18+
"RangeAnalysisScriptedSetup": {
19+
"type": "object",
20+
"description": "Environment for a Range Analysis step.",
21+
"additionalProperties": false,
22+
"properties": {
23+
"nodeType": { "const": "RangeAnalysisScriptedSetup", "description": "Discriminator. Must be exactly this value." },
24+
"club": {
25+
"type": "string",
26+
"minLength": 1,
27+
"enum": [
28+
"None", "Drv", "_2W", "_3W", "_4W", "_5W", "_6W", "_7W", "_8W", "_9W",
29+
"_1H", "_2H", "_3H", "_4H", "_5H", "_6H", "_7H", "_8H", "_9H",
30+
"_1I", "_2I", "_3I", "_4I", "_5I", "_6I", "_7I", "_8I", "_9I",
31+
"_PW", "_SW", "_LW", "_50W", "_52W", "_54W", "_56W", "_58W", "_60W", "Putt"
32+
],
33+
"description": "Club specification for the range analysis shot.",
34+
"default": "Drv"
35+
},
36+
"distance": { "type": "number", "minimum": 0, "description": "Required distance to the target in meters." }
37+
},
38+
"required": ["nodeType", "club", "distance"]
39+
},
40+
"RangeAnalysisScriptedUI": {
41+
"type": "object",
42+
"description": "UI hints/overrides for Range Analysis. Empty object means defaults.",
43+
"additionalProperties": false,
44+
"properties": {
45+
"nodeType": { "const": "RangeAnalysisScriptedUI" },
46+
"targetAvailable": { "type": "boolean", "default": true },
47+
"activeDataTiles": { "type": "array", "items": { "$ref": "shared.schema.json#/$defs/ParameterName" }, "maxItems": 8, "default": [] },
48+
"shotListParameters": { "type": "array", "items": { "$ref": "shared.schema.json#/$defs/ParameterName" }, "default": ["Total", "Carry", "BallSpeed"] },
49+
"defaultShotListParameter": { "$ref": "shared.schema.json#/$defs/ParameterName", "default": "Carry" },
50+
"beforeShot": { "$ref": "shared.schema.json#/$defs/UIFrameAction" },
51+
"duringShot": { "$ref": "shared.schema.json#/$defs/UIFrameAction" },
52+
"afterShot": { "$ref": "shared.schema.json#/$defs/UIFrameAction" }
53+
},
54+
"required": ["nodeType"]
55+
},
56+
"RangeAnalysisScriptedLogic": {
57+
"type": "object",
58+
"description": "Evaluation logic for a Range Analysis step: setup + success/fail conditions + flow flags.",
59+
"additionalProperties": false,
60+
"properties": {
61+
"nodeType": { "const": "RangeAnalysisScriptedLogic" },
62+
"setup": { "$ref": "#/$defs/RangeAnalysisScriptedSetup" },
63+
"successCondition": { "$ref": "#/$defs/RangeAnalysisScriptedConditions" },
64+
"failCondition": { "$ref": "#/$defs/RangeAnalysisScriptedConditions" },
65+
"canRetry": { "type": "boolean", "default": false },
66+
"skipOnSuccess": { "type": "boolean", "default": false }
67+
},
68+
"required": ["nodeType", "setup", "successCondition", "skipOnSuccess"]
69+
},
70+
"RangeAnalysisScriptedStep": {
71+
"type": "object",
72+
"description": "One step in a Range Analysis activity.",
73+
"additionalProperties": false,
74+
"properties": {
75+
"nodeType": { "const": "RangeAnalysisScriptedStep" },
76+
"id": { "$ref": "shared.schema.json#/$defs/IdString" },
77+
"introMessage": { "$ref": "shared.schema.json#/$defs/Message" },
78+
"successMessage": { "$ref": "shared.schema.json#/$defs/Message" },
79+
"failMessage": { "$ref": "shared.schema.json#/$defs/Message" },
80+
"logic": { "$ref": "#/$defs/RangeAnalysisScriptedLogic" },
81+
"ui": { "$ref": "#/$defs/RangeAnalysisScriptedUI" },
82+
"greenTarget": { "type": "boolean", "default": false },
83+
"targetWidthHCP": { "type": "number", "minimum": 0 },
84+
"targetWidthPro": { "type": "number", "minimum": 0 }
85+
},
86+
"required": ["nodeType", "id", "introMessage", "successMessage", "failMessage", "logic", "ui"]
87+
},
88+
"RangeAnalysisScriptedActivity": {
89+
"$anchor": "Activity",
90+
"type": "object",
91+
"description": "Activity targeting the Range Analysis app. Steps run in order.",
92+
"additionalProperties": false,
93+
"properties": {
94+
"nodeType": { "const": "RangeAnalysisScriptedActivity" },
95+
"id": { "$ref": "shared.schema.json#/$defs/IdString" },
96+
"introMessage": { "$ref": "shared.schema.json#/$defs/Message" },
97+
"endMessage": { "$ref": "shared.schema.json#/$defs/Message" },
98+
"steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/RangeAnalysisScriptedStep" } }
99+
},
100+
"required": ["nodeType", "id", "introMessage", "endMessage", "steps"]
101+
}
102+
}
103+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.trackman.com/app-scripting/1-0-0/shared.schema.json",
4+
"title": "Shared App Scripting definitions",
5+
"$defs": {
6+
"IdString": { "type": "string", "pattern": "^[a-zA-Z0-9_-]+$" },
7+
"Message": { "type": "object", "additionalProperties": false, "properties": { "text": { "type": "string" }, "language": { "type": "string" } }, "required": ["text"] },
8+
"StartMode": { "type": "string", "enum": ["Manual", "Auto"] },
9+
"EndMode": { "type": "string", "enum": ["Manual", "Auto"] },
10+
"ParameterName": { "type": "string", "enum": ["Total", "Carry", "BallSpeed", "ClubHeadSpeed"] },
11+
"ConditionType": { "type": "string", "enum": ["AtLeast", "AtMost", "Exact"] },
12+
"ConditionClause": { "type": "object", "additionalProperties": false, "properties": { "parameter": { "$ref": "#/ $defs/ParameterName" }, "operator": { "$ref": "#/ $defs/ConditionType" }, "value": { "type": "number" } }, "required": ["parameter", "operator", "value"] },
13+
"UIFrameAction": { "type": "object", "additionalProperties": false, "properties": { "action": { "type": "string" }, "params": { "type": "object" }, "delayMs": { "type": "integer", "minimum": 0 } }, "required": ["action"] }
14+
}
15+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.trackman.com/app-scripting/1-0-0/activity-performance-center.json",
4+
"title": "Performance Center Activity",
5+
"$defs": {
6+
"PerformanceCenterScriptedConditions": {
7+
"type": "object",
8+
"description": "Success/fail condition for Performance Center steps. Same semantics as Range Analysis conditions.",
9+
"additionalProperties": false,
10+
"properties": {
11+
"nodeType": { "const": "PerformanceCenterScriptedConditions", "description": "Discriminator. Must be exactly this value." },
12+
"shots": { "type": "integer", "minimum": 1, "description": "Threshold count." },
13+
"conditionType": { "$ref": "shared.schema.json#/$defs/ConditionType" },
14+
"conditions": { "type": "array", "minItems": 0, "items": { "$ref": "shared.schema.json#/$defs/ConditionClause" }, "default": [] }
15+
},
16+
"required": ["nodeType", "shots"]
17+
},
18+
"PerformanceCenterApproachScriptedSetup": {
19+
"type": "object",
20+
"description": "Approach-shot scenario configuration in Performance Center.",
21+
"additionalProperties": false,
22+
"properties": {
23+
"nodeType": { "const": "PerformanceCenterApproachScriptedSetup", "description": "Discriminator. Must be exactly this value." },
24+
"hole": { "type": "integer", "minimum": 1, "description": "Hole number (1-based)." },
25+
"pin": { "type": "integer", "minimum": 1, "description": "Pin index on the selected hole (1-based)." },
26+
"playerCategory": { "type": "string", "enum": ["Handicap", "PGA", "LPGA"], "default": "Handicap", "description": "Baseline cohort for strokes-gained and contours." },
27+
"hcp": { "type": "integer", "minimum": 0, "maximum": 15, "description": "Player handicap used for baselines." },
28+
"gender": { "type": "string", "enum": ["Male", "Female", "Unspecified"], "default": "Unspecified", "description": "Baseline cohort dimension." },
29+
"minDistance": { "type": "number", "minimum": 0, "description": "Minimum approach distance in meters.", "default": 30.0 },
30+
"maxDistance": { "type": "number", "minimum": 0, "description": "Maximum approach distance in meters.", "default": 220.0 },
31+
"club": { "type": "string", "description": "Club specification for the approach shot.", "default": "Drv" }
32+
},
33+
"required": ["nodeType", "hole", "pin", "playerCategory", "hcp", "gender", "minDistance", "maxDistance"]
34+
},
35+
"PerformanceCenterTeeShotsScriptedSetup": {
36+
"type": "object",
37+
"description": "Tee-shot scenario configuration in Performance Center.",
38+
"additionalProperties": false,
39+
"properties": {
40+
"nodeType": { "const": "PerformanceCenterTeeShotsScriptedSetup", "description": "Discriminator. Must be exactly this value." },
41+
"hole": { "type": "integer", "minimum": 1, "description": "Hole number (1-based)." },
42+
"playerCategory": { "type": "string", "enum": ["Handicap", "PGA", "LPGA"], "default": "Handicap", "description": "Baseline cohort for strokes-gained and contours." },
43+
"hcp": { "type": "integer", "minimum": 0, "maximum": 15, "description": "Player handicap used for baselines. Required only when playerCategory is 'Handicap'." },
44+
"gender": { "type": "string", "enum": ["Male", "Female", "Unspecified"], "default": "Unspecified", "description": "Baseline cohort dimension." },
45+
"courseDistance": { "type": "integer", "minimum": 1000, "maximum": 9000, "description": "Total course distance in meters (context for tee-shot modeling).", "default": 6900 },
46+
"club": { "type": "string", "description": "Club specification for the tee shot.", "default": "Drv" }
47+
},
48+
"required": ["nodeType", "hole", "playerCategory", "gender", "courseDistance"],
49+
"allOf": [
50+
{
51+
"if": { "properties": { "playerCategory": { "const": "Handicap" } } },
52+
"then": { "required": ["hcp"] }
53+
}
54+
]
55+
},
56+
"PerformanceCenterScriptedUI": {
57+
"type": "object",
58+
"description": "UI hints/overrides for Performance Center. Empty object means defaults.",
59+
"additionalProperties": false,
60+
"properties": {
61+
"nodeType": { "const": "PerformanceCenterScriptedUI" },
62+
"targetAvailable": { "type": "boolean", "default": true },
63+
"activeDataTiles": { "type": "array", "items": { "$ref": "shared.schema.json#/$defs/ParameterName" }, "maxItems": 8, "default": [] },
64+
"shotListParameters": { "type": "array", "items": { "$ref": "shared.schema.json#/$defs/ParameterName" }, "default": ["Total", "Carry", "BallSpeed"] },
65+
"defaultShotListParameter": { "$ref": "shared.schema.json#/$defs/ParameterName", "default": "Carry" },
66+
"beforeShot": { "$ref": "shared.schema.json#/$defs/UIFrameAction" },
67+
"duringShot": { "$ref": "shared.schema.json#/$defs/UIFrameAction" },
68+
"afterShot": { "$ref": "shared.schema.json#/$defs/UIFrameAction" }
69+
},
70+
"required": ["nodeType"]
71+
},
72+
"PerformanceCenterScriptedLogic": {
73+
"type": "object",
74+
"description": "Evaluation logic for a Performance Center step: setup + success/fail conditions + flow flags.",
75+
"additionalProperties": false,
76+
"properties": {
77+
"nodeType": { "const": "PerformanceCenterScriptedLogic" },
78+
"setup": {
79+
"oneOf": [
80+
{ "$ref": "#/$defs/PerformanceCenterApproachScriptedSetup" },
81+
{ "$ref": "#/$defs/PerformanceCenterTeeShotsScriptedSetup" }
82+
],
83+
"description": "Pick exactly one setup variant matching the step scenario."
84+
},
85+
"successCondition": { "$ref": "#/$defs/PerformanceCenterScriptedConditions" },
86+
"failCondition": { "$ref": "#/$defs/PerformanceCenterScriptedConditions" },
87+
"canRetry": { "type": "boolean", "default": false },
88+
"skipOnSuccess": { "type": "boolean", "default": false }
89+
},
90+
"required": ["nodeType", "setup", "successCondition"]
91+
},
92+
"PerformanceCenterScriptedStep": {
93+
"type": "object",
94+
"description": "One step in a Performance Center activity.",
95+
"additionalProperties": false,
96+
"properties": {
97+
"nodeType": { "const": "PerformanceCenterScriptedStep" },
98+
"id": { "$ref": "shared.schema.json#/$defs/IdString" },
99+
"introMessage": { "$ref": "shared.schema.json#/$defs/Message" },
100+
"successMessage": { "$ref": "shared.schema.json#/$defs/Message" },
101+
"failMessage": { "$ref": "shared.schema.json#/$defs/Message" },
102+
"logic": { "$ref": "#/$defs/PerformanceCenterScriptedLogic" },
103+
"ui": { "$ref": "#/$defs/PerformanceCenterScriptedUI" }
104+
},
105+
"required": ["nodeType", "id", "introMessage", "successMessage", "failMessage", "logic", "ui"]
106+
},
107+
"PerformanceCenterScriptedActivity": {
108+
"$anchor": "Activity",
109+
"type": "object",
110+
"description": "Activity targeting the Performance Center app. Steps run in order.",
111+
"additionalProperties": false,
112+
"properties": {
113+
"nodeType": { "const": "PerformanceCenterScriptedActivity" },
114+
"id": { "$ref": "shared.schema.json#/$defs/IdString" },
115+
"introMessage": { "$ref": "shared.schema.json#/$defs/Message" },
116+
"endMessage": { "$ref": "shared.schema.json#/$defs/Message" },
117+
"steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/PerformanceCenterScriptedStep" } }
118+
},
119+
"required": ["nodeType", "id", "introMessage", "endMessage", "steps"]
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)