openskidata-format 5.2.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@ tslib_1.__exportStar(require("./Lift"), exports);
7
7
  tslib_1.__exportStar(require("./LiftNameFormatter"), exports);
8
8
  tslib_1.__exportStar(require("./Location"), exports);
9
9
  tslib_1.__exportStar(require("./Run"), exports);
10
+ tslib_1.__exportStar(require("./RunDifficultyConvention"), exports);
11
+ tslib_1.__exportStar(require("./SlopeGradingScale"), exports);
10
12
  tslib_1.__exportStar(require("./SkiArea"), exports);
11
13
  tslib_1.__exportStar(require("./SnowCoverHistory"), exports);
12
14
  tslib_1.__exportStar(require("./Source"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,6DAAkC;AAClC,wDAA6B;AAC7B,iDAAsB;AACtB,8DAAmC;AACnC,qDAA0B;AAC1B,gDAAqB;AACrB,oDAAyB;AACzB,6DAAkC;AAClC,mDAAwB;AACxB,mDAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,6DAAkC;AAClC,wDAA6B;AAC7B,iDAAsB;AACtB,8DAAmC;AACnC,qDAA0B;AAC1B,gDAAqB;AACrB,oEAAyC;AACzC,8DAAmC;AACnC,oDAAyB;AACzB,6DAAkC;AAClC,mDAAwB;AACxB,mDAAwB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openskidata-format",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "description": "Data format for OpenSkiMap.org",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,7 +33,10 @@
33
33
  "typescript": "^5"
34
34
  },
35
35
  "dependencies": {
36
+ "@turf/boolean-point-in-polygon": "^7.2.0",
37
+ "@turf/center": "^7.2.0",
36
38
  "@turf/distance": "^7.2.0",
39
+ "@turf/helpers": "^7.2.0",
37
40
  "@turf/length": "^7.2.0",
38
41
  "@turf/line-chunk": "^7.2.0",
39
42
  "@turf/meta": "^7.2.0",
@@ -8,10 +8,10 @@ import { getLiftElevationData, LiftFeature, LiftType } from './Lift'
8
8
  import {
9
9
  getRunElevationData,
10
10
  RunDifficulty,
11
- RunDifficultyConvention,
12
11
  RunFeature,
13
12
  RunUse,
14
13
  } from './Run'
14
+ import { RunDifficultyConvention } from './RunDifficultyConvention'
15
15
  import { Status } from './Status'
16
16
 
17
17
  describe('ElevationProfile', () => {
package/src/Run.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  getProfileGeometry,
7
7
  } from './ElevationProfile'
8
8
  import { FeatureType } from './FeatureType'
9
+ import { RunDifficultyConvention } from './RunDifficultyConvention'
9
10
  import { SkiAreaSummaryFeature } from './SkiArea'
10
11
  import { SnowCoverHistory } from './SnowCoverHistory'
11
12
  import { Source } from './Source'
@@ -131,39 +132,6 @@ export enum RunColorValue {
131
132
  GREY = 'hsl(0, 0%, 35%)',
132
133
  }
133
134
 
134
- /**
135
- * Run difficulty colors vary by region. This enum defines the color convention used for runs at a ski area.
136
- * @enum {string}
137
- */
138
- export enum RunDifficultyConvention {
139
- /**
140
- * European color convention:
141
- * - Green: Novice
142
- * - Blue: Easy
143
- * - Red: Intermediate
144
- * - Black: Advanced/Expert
145
- * - Orange: Freeride/Extreme
146
- */
147
- EUROPE = 'europe',
148
-
149
- /**
150
- * Japanese color convention:
151
- * - Green: Novice/Easy
152
- * - Red: Intermediate
153
- * - Black: Advanced/Expert
154
- * - Orange: Freeride/Extreme
155
- */
156
- JAPAN = 'japan',
157
-
158
- /**
159
- * North American color convention:
160
- * - Green: Novice/Easy
161
- * - Blue: Intermediate
162
- * - Black: Advanced/Expert
163
- * - Orange: Freeride/Extreme
164
- */
165
- NORTH_AMERICA = 'north_america',
166
- }
167
135
 
168
136
  export function getRunElevationData(feature: RunFeature): ElevationData | null {
169
137
  const geometry = feature.geometry
@@ -0,0 +1,79 @@
1
+ import { getRunDifficultyConvention, RunDifficultyConvention } from "./RunDifficultyConvention";
2
+
3
+ describe("getRunDifficultyConvention", () => {
4
+ it("should return JAPAN for locations in Japan", () => {
5
+ // Point in Japan (Tokyo)
6
+ const tokyoGeometry = {
7
+ type: "Point" as const,
8
+ coordinates: [139.6917, 35.6895]
9
+ };
10
+
11
+ expect(getRunDifficultyConvention(tokyoGeometry)).toBe(RunDifficultyConvention.JAPAN);
12
+ });
13
+
14
+ it("should return NORTH_AMERICA for locations in North America", () => {
15
+ // Point in Colorado, USA
16
+ const coloradoGeometry = {
17
+ type: "Point" as const,
18
+ coordinates: [-106.3731, 39.1911]
19
+ };
20
+
21
+ expect(getRunDifficultyConvention(coloradoGeometry)).toBe(RunDifficultyConvention.NORTH_AMERICA);
22
+
23
+ // Point in British Columbia, Canada
24
+ const bcGeometry = {
25
+ type: "Point" as const,
26
+ coordinates: [-123.1207, 49.2827]
27
+ };
28
+
29
+ expect(getRunDifficultyConvention(bcGeometry)).toBe(RunDifficultyConvention.NORTH_AMERICA);
30
+ });
31
+
32
+ it("should return EUROPE for locations in Europe", () => {
33
+ // Point in the Alps (Chamonix, France)
34
+ const chamonixGeometry = {
35
+ type: "Point" as const,
36
+ coordinates: [6.8694, 45.9237]
37
+ };
38
+
39
+ expect(getRunDifficultyConvention(chamonixGeometry)).toBe(RunDifficultyConvention.EUROPE);
40
+
41
+ // Point in Austria
42
+ const austriaGeometry = {
43
+ type: "Point" as const,
44
+ coordinates: [13.7558, 47.8095]
45
+ };
46
+
47
+ expect(getRunDifficultyConvention(austriaGeometry)).toBe(RunDifficultyConvention.EUROPE);
48
+ });
49
+
50
+ it("should return EUROPE as default for other locations", () => {
51
+ // Point in South America (should default to Europe)
52
+ const southAmericaGeometry = {
53
+ type: "Point" as const,
54
+ coordinates: [-58.3816, -34.6037] // Buenos Aires, Argentina
55
+ };
56
+
57
+ expect(getRunDifficultyConvention(southAmericaGeometry)).toBe(RunDifficultyConvention.EUROPE);
58
+ });
59
+
60
+ it("should work with LineString geometry", () => {
61
+ // LineString crossing through Europe
62
+ const lineGeometry = {
63
+ type: "LineString" as const,
64
+ coordinates: [[6.8, 45.9], [6.9, 46.0]]
65
+ };
66
+
67
+ expect(getRunDifficultyConvention(lineGeometry)).toBe(RunDifficultyConvention.EUROPE);
68
+ });
69
+
70
+ it("should work with Polygon geometry", () => {
71
+ // Polygon in North America
72
+ const polygonGeometry = {
73
+ type: "Polygon" as const,
74
+ coordinates: [[[-106.4, 39.1], [-106.3, 39.1], [-106.3, 39.2], [-106.4, 39.2], [-106.4, 39.1]]]
75
+ };
76
+
77
+ expect(getRunDifficultyConvention(polygonGeometry)).toBe(RunDifficultyConvention.NORTH_AMERICA);
78
+ });
79
+ });
@@ -0,0 +1,335 @@
1
+ import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
2
+ import turfCenter from "@turf/center";
3
+ import * as turf from "@turf/helpers";
4
+ import { AllGeoJSON } from "@turf/helpers";
5
+
6
+ /**
7
+ * Run difficulty colors vary by region. This enum defines the color convention used for runs at a ski area.
8
+ * @enum {string}
9
+ */
10
+ export enum RunDifficultyConvention {
11
+ /**
12
+ * European color convention:
13
+ * - Green: Novice
14
+ * - Blue: Easy
15
+ * - Red: Intermediate
16
+ * - Black: Advanced/Expert
17
+ * - Orange: Freeride/Extreme
18
+ */
19
+ EUROPE = 'europe',
20
+
21
+ /**
22
+ * Japanese color convention:
23
+ * - Green: Novice/Easy
24
+ * - Red: Intermediate
25
+ * - Black: Advanced/Expert
26
+ * - Orange: Freeride/Extreme
27
+ */
28
+ JAPAN = 'japan',
29
+
30
+ /**
31
+ * North American color convention:
32
+ * - Green: Novice/Easy
33
+ * - Blue: Intermediate
34
+ * - Black: Advanced/Expert
35
+ * - Orange: Freeride/Extreme
36
+ */
37
+ NORTH_AMERICA = 'north_america',
38
+ }
39
+
40
+ const northAmericanConventionGeometry = turf.multiPolygon([
41
+ [
42
+ [
43
+ [66.89889168301036, 22.98946421817959],
44
+ [76.79011657384558, 4.2607118936878265],
45
+ [112.5459757578734, -40.008871147786486],
46
+ [166.64372809287335, -58.19200446079054],
47
+ [191.91699393212554, -33.377687858720755],
48
+ [192.65370948033006, -8.971607939355977],
49
+ [140.68354997294796, 5.451024881476499],
50
+ [123.38582294700518, 21.801329456101513],
51
+ [122.25942048875993, 24.243081370534554],
52
+ [123.02414890399393, 26.354744126525432],
53
+ [129.68307711216244, 35.3374262814546],
54
+ [131.36509887116028, 39.1827837685222],
55
+ [130.5715844381864, 42.515964349309684],
56
+ [130.62108313985783, 42.63370843853855],
57
+ [130.39263902117034, 42.73714858581644],
58
+ [130.8150956808529, 42.87954610777132],
59
+ [131.04334909066392, 42.88226217082041],
60
+ [131.33954328617205, 43.445079879213296],
61
+ [131.191137752773, 43.53879786242706],
62
+ [131.2860140618261, 44.06115319070142],
63
+ [131.1086866768622, 44.71097030226514],
64
+ [130.95332209785204, 44.84377389211244],
65
+ [131.56223386930952, 45.01998391706314],
66
+ [131.87876159757576, 45.342467064732745],
67
+ [131.9445424786545, 45.26381674117374],
68
+ [132.89886314033083, 45.04768363738535],
69
+ [132.9409663928247, 45.020634782943716],
70
+ [133.12560828825156, 45.14828761444474],
71
+ [133.11406817721956, 45.23774574998686],
72
+ [133.1686920707706, 45.49559658174417],
73
+ [133.4044528436404, 45.59600211321589],
74
+ [133.49367119277423, 45.87840483196845],
75
+ [133.57649823904808, 45.88061866181769],
76
+ [133.7230811284722, 46.06662995573109],
77
+ [133.68166349871666, 46.137321119014274],
78
+ [133.9014556853037, 46.24315756590036],
79
+ [134.29060710292293, 47.44981009549741],
80
+ [134.53603145724082, 47.47580868032259],
81
+ [134.80050117570937, 47.73143995381383],
82
+ [134.54808493637842, 48.00270638588145],
83
+ [134.7902354911858, 48.38077517538687],
84
+ [134.53852703049813, 48.414602674179406],
85
+ [134.05426284432252, 48.33207866806839],
86
+ [133.44255382292891, 48.11130941788082],
87
+ [133.06661598961256, 48.102793716410616],
88
+ [132.65561957214425, 47.92377254119751],
89
+ [132.57597035647728, 47.73126763647102],
90
+ [131.5872859174675, 47.669086096155525],
91
+ [130.978760673039, 47.70552624852317],
92
+ [130.8927298265839, 47.92147467660291],
93
+ [130.69208001471225, 48.07898424194457],
94
+ [130.8424973965307, 48.32747681044523],
95
+ [130.53333624266037, 48.638203333369944],
96
+ [130.69902773150022, 48.86294984494779],
97
+ [130.4313260036679, 48.91144552665949],
98
+ [130.2336273608912, 48.877796693265594],
99
+ [129.49472335519903, 49.445146325369194],
100
+ [128.6404925727599, 49.6395594299683],
101
+ [127.95892224407356, 49.62425806475295],
102
+ [127.56973394676123, 49.842755131278835],
103
+ [127.6749910879272, 50.240140628289964],
104
+ [127.45368458653832, 50.26847480259133],
105
+ [127.37394005798404, 50.29288471184299],
106
+ [127.32612719828853, 50.34379944487219],
107
+ [127.37997900840315, 50.60653687131031],
108
+ [127.16325020595207, 50.933036917572906],
109
+ [126.99177818739395, 51.326954509452236],
110
+ [126.33131963313707, 52.493153867333206],
111
+ [126.09655832692533, 52.86710580508279],
112
+ [125.18461572471739, 53.21778527809076],
113
+ [123.62905555865535, 53.56957077991163],
114
+ [122.14662682326076, 53.507610554797225],
115
+ [120.81940759451805, 53.31174251524433],
116
+ [119.95478692741125, 52.77983494498105],
117
+ [120.02183577608542, 52.55624852160162],
118
+ [120.59821023820314, 52.5562523256705],
119
+ [120.65182146309388, 52.027454302929755],
120
+ [120.00845804883363, 51.63400833664596],
121
+ [119.10923570584242, 50.3653464992334],
122
+ [119.33042992474253, 50.30545934524457],
123
+ [119.21648675850292, 50.099528593865784],
124
+ [118.93783039700338, 49.98458223887849],
125
+ [118.54626899510839, 49.94616013995508],
126
+ [117.80663959739081, 49.53647108800752],
127
+ [117.484738258086, 49.624317990557614],
128
+ [117.26607476489426, 49.63477188589076],
129
+ [116.96468681768641, 49.73160402967815],
130
+ [116.62825050755794, 49.944503706705376],
131
+ [116.2287910451044, 50.03623236447976],
132
+ [115.97912115005505, 49.97893073129566],
133
+ [115.72585372832015, 49.87560524136032],
134
+ [115.38340104847777, 49.935338883138456],
135
+ [115.15157871232401, 50.03624558574222],
136
+ [114.96972180858182, 50.18262812854161],
137
+ [114.32823723216535, 50.27374466694857],
138
+ [113.21615782676918, 49.84014337192383],
139
+ [113.06279976594055, 49.60262851502978],
140
+ [112.75961978011298, 49.50544853175836],
141
+ [112.4528903096238, 49.51941937053812],
142
+ [111.93911320274538, 49.37324774723086],
143
+ [111.69083700584588, 49.38804243172055],
144
+ [110.68965090965844, 49.16705432804406],
145
+ [108.61062678042163, 49.33457873762259],
146
+ [107.90316280555385, 49.97532248790398],
147
+ [106.49948671672877, 50.3809827302172],
148
+ [105.51746011619525, 50.48702476586922],
149
+ [103.97795584841299, 50.133831277984996],
150
+ [102.69196601175406, 50.37681484681099],
151
+ [102.27144249887641, 50.87948727040293],
152
+ [102.17444849785716, 51.35640391793228],
153
+ [100.63003834780625, 51.738599556839574],
154
+ [98.92412930445079, 52.152271807237554],
155
+ [98.0263146497278, 51.38702212297895],
156
+ [97.83223938583137, 50.91503753447586],
157
+ [98.30141292582249, 50.51549014567553],
158
+ [98.03452228766315, 50.01401927081076],
159
+ [97.21087912958029, 49.75344974439781],
160
+ [96.59617521697089, 49.92558626439808],
161
+ [94.58073504473032, 50.071206832869876],
162
+ [94.44884921665886, 50.25288523325358],
163
+ [94.28227879098631, 50.59029357818193],
164
+ [93.06055432240078, 50.6108167038102],
165
+ [92.95500531764452, 50.764378755264715],
166
+ [92.38044935493656, 50.81536176617482],
167
+ [89.61447548394369, 49.896510834163024],
168
+ [89.41209157088667, 49.593951299041436],
169
+ [87.21941106111126, 49.136371106937105],
170
+ [86.47691458036888, 48.52706996107682],
171
+ [85.66792655187515, 48.41217050021373],
172
+ [85.61001315938637, 47.097608820611185],
173
+ [83.06577876367635, 47.1684932958469],
174
+ [82.19603900970611, 45.39598594758252],
175
+ [79.94680702146206, 44.995940936938524],
176
+ [80.74758671786947, 43.25101970631087],
177
+ [80.16296382083789, 42.42004311892032],
178
+ [79.08808560905646, 42.80565581050615],
179
+ [77.46543003728954, 42.93866114713731],
180
+ [77.30266016034727, 42.91577009179525],
181
+ [77.06944317811468, 42.98941184436538],
182
+ [76.83954492079482, 42.95784584611252],
183
+ [76.66706605000616, 42.91054018927406],
184
+ [76.35054751194656, 42.86314251596045],
185
+ [76.22106905960021, 42.92109675548289],
186
+ [75.8499512176796, 42.944841027684475],
187
+ [75.69647619703395, 42.79434701877443],
188
+ [75.20518050373951, 42.86058166470994],
189
+ [74.86716288299183, 42.99486162795807],
190
+ [74.21214208437436, 43.26799034589942],
191
+ [73.54918053004673, 43.03445951036437],
192
+ [73.43569691290458, 42.59058989745361],
193
+ [73.50713573720739, 42.42885549027292],
194
+ [73.32430827244477, 42.43964242187812],
195
+ [73.28138720704561, 42.524654623049486],
196
+ [72.89688006931604, 42.53825798475941],
197
+ [72.7028920768594, 42.65445195418786],
198
+ [71.8205490156389, 42.84297257066001],
199
+ [71.24172502287257, 42.76218198674192],
200
+ [70.96542642702568, 42.45295945325228],
201
+ [70.87574064610243, 42.288978943546994],
202
+ [70.93667564676599, 42.25956939262474],
203
+ [71.0522698554054, 42.28801700409892],
204
+ [71.26892670629547, 42.19664779423837],
205
+ [70.22467025584973, 41.6109136918285],
206
+ [70.1871419707528, 41.52357559397731],
207
+ [70.29521282660394, 41.5196557335768],
208
+ [70.4885172051716, 41.39563567019803],
209
+ [70.6908234400903, 41.47973822440426],
210
+ [70.78334977579652, 41.37596799777336],
211
+ [70.7936135992125, 41.23200478517444],
212
+ [71.40193377758987, 41.189890843929476],
213
+ [71.72132931443616, 41.463007098837124],
214
+ [72.25976659039807, 41.036213505586716],
215
+ [73.12473655458163, 40.821214468109844],
216
+ [71.8274169831183, 40.219535506292345],
217
+ [71.2093915709481, 40.35194316359275],
218
+ [70.70839519610914, 40.047767583705706],
219
+ [70.00814064760502, 40.19597188360018],
220
+ [69.3238929275289, 39.96163997362652],
221
+ [69.25288425833449, 39.8365015771121],
222
+ [69.36807176732333, 39.53622995828479],
223
+ [70.5656905159378, 39.611522993563625],
224
+ [70.81017094805003, 39.40296443017286],
225
+ [71.05478901580443, 39.42623263483682],
226
+ [71.09537841230028, 39.521081174175976],
227
+ [71.48723105871241, 39.61179598590786],
228
+ [71.80293870931277, 39.289369010362776],
229
+ [72.03176071465103, 39.344791211184486],
230
+ [72.22037536907436, 39.19478948035075],
231
+ [72.34794908849406, 39.34434407454637],
232
+ [73.15397827282933, 39.35800161267082],
233
+ [73.41580743762637, 39.46694232025965],
234
+ [73.60494023346439, 39.469004217709056],
235
+ [73.53306087489301, 39.24817612724672],
236
+ [73.8401473956308, 38.955283153545196],
237
+ [73.7178756559239, 38.88418224181672],
238
+ [73.84575285445322, 38.5733588129749],
239
+ [74.19825648155071, 38.625225936216],
240
+ [74.73465165940527, 38.39729684471283],
241
+ [74.94429646804616, 37.74563365375093],
242
+ [75.09730124153691, 37.34874288728962],
243
+ [74.47556092367677, 37.22736548435755],
244
+ [74.52571774786139, 37.04804932382365],
245
+ [72.64281263069017, 36.9965169904729],
246
+ [71.27151437563325, 36.14385342653641],
247
+ [71.70051938813555, 35.31553980310994],
248
+ [70.91367870839377, 34.02947262017156],
249
+ [69.8657881549984, 33.97753268150575],
250
+ [70.19479291508452, 33.38872790844742],
251
+ [69.48427263502771, 32.94309627730759],
252
+ [69.17043362955638, 31.802649394624297],
253
+ [66.5660130962763, 31.1468844695182],
254
+ [66.39058495939196, 29.902900359253024],
255
+ [64.20728972399988, 29.470320322411112],
256
+ [62.39830055544061, 29.433474533828033],
257
+ [60.82809795436239, 29.876493049104326],
258
+ [61.819412883544715, 28.5413645023537],
259
+ [62.838210084807116, 28.1758941784838],
260
+ [62.87712480493187, 26.710220153319582],
261
+ [61.95649723937791, 26.202543172995433],
262
+ [61.64164473778666, 25.062349569223997],
263
+ [66.89889168301036, 22.98946421817959],
264
+ ],
265
+ ],
266
+ [
267
+ [
268
+ [-79.49790751939359, 8.895517276865164],
269
+ [-80.09116426661198, 9.489400626216977],
270
+ [-71.5226805789838, 14.570830502555324],
271
+ [-64.296660455746, 16.87497218957077],
272
+ [-63.50670575144407, 19.468079078229948],
273
+ [-46.04319359052067, 49.81687541607755],
274
+ [-57.24573007399778, 67.81957009723368],
275
+ [-74.74198803509906, 76.55978940288878],
276
+ [-73.60375960527375, 78.39636019182609],
277
+ [-67.92218140574312, 80.61698801540712],
278
+ [-59.076220860081435, 82.41962573871615],
279
+ [-68.9778162806643, 85.05112877980659],
280
+ [-169.10721706859002, 69.87119013352208],
281
+ [-168.82669211383998, 64.59846733544799],
282
+ [-172.31141325730604, 63.991833108168834],
283
+ [-192.1254235906623, 52.646873605362146],
284
+ [-166.3003429543922, 12.967564352770154],
285
+ [-79.6692367415715, 4.562414945897046],
286
+ [-79.49790751939359, 8.895517276865164],
287
+ ],
288
+ ],
289
+ ]);
290
+
291
+ const japanConventionGeometry = turf.polygon([
292
+ [
293
+ [122.40443764161375, 24.25555191895947],
294
+ [123.22422482046358, 22.664415921202675],
295
+ [131.6668409404955, 27.1734104531445],
296
+ [141.6724497786463, 33.41882632781292],
297
+ [152.21247459573226, 45.19087135255526],
298
+ [154.7040665173107, 48.05238412051253],
299
+ [149.47388354609916, 49.86405083649407],
300
+ [144.62198341555745, 55.122855332829886],
301
+ [141.85000003174838, 54.453056889632535],
302
+ [141.56865023975553, 53.237305271866575],
303
+ [141.5658284519161, 52.12730212591498],
304
+ [140.86177532698593, 47.83608043534858],
305
+ [129.38176008175282, 34.88162789041118],
306
+ [122.40443764161375, 24.25555191895947],
307
+ ],
308
+ ]);
309
+
310
+ /**
311
+ * Determines the run difficulty convention for a given geographic location.
312
+ * Based on the center point of the geometry, returns the appropriate regional
313
+ * convention for ski run difficulty ratings.
314
+ *
315
+ * @param geojson - GeoJSON geometry to determine the center location from
316
+ * @returns The appropriate run difficulty convention for the location
317
+ * @throws Error if the center of geometry cannot be determined
318
+ */
319
+ export function getRunDifficultyConvention(
320
+ geojson: AllGeoJSON,
321
+ ): RunDifficultyConvention {
322
+ const point = turfCenter(geojson).geometry;
323
+ if (!point) {
324
+ throw "Cannot determine center of geometry";
325
+ }
326
+
327
+ if (booleanPointInPolygon(point, japanConventionGeometry)) {
328
+ return RunDifficultyConvention.JAPAN;
329
+ } else if (booleanPointInPolygon(point, northAmericanConventionGeometry)) {
330
+ return RunDifficultyConvention.NORTH_AMERICA;
331
+ } else {
332
+ return RunDifficultyConvention.EUROPE;
333
+ }
334
+ }
335
+
package/src/SkiArea.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { FeatureType } from './FeatureType'
2
2
  import { LiftType } from './Lift'
3
3
  import { Location } from './Location'
4
- import { RunDifficulty, RunDifficultyConvention } from './Run'
4
+ import { RunDifficulty } from './Run'
5
+ import { RunDifficultyConvention } from './RunDifficultyConvention'
5
6
  import { SnowCoverHistory } from './SnowCoverHistory'
6
7
  import { Source } from './Source'
7
8
  import { Status } from './Status'
@@ -0,0 +1,129 @@
1
+ import { RunDifficulty, RunUse } from "./Run";
2
+ import { getEstimatedRunDifficulty, getSlopeGradingScale } from "./SlopeGradingScale";
3
+
4
+ describe("getEstimatedRunDifficulty", () => {
5
+ it("should return null for steepness below minimum threshold", () => {
6
+ const downhillScale = getSlopeGradingScale({
7
+ type: "Feature",
8
+ geometry: { type: "LineString", coordinates: [] },
9
+ properties: {
10
+ type: "Run" as any,
11
+ uses: [RunUse.Downhill],
12
+ id: "test",
13
+ name: null,
14
+ ref: null,
15
+ status: "operating" as any,
16
+ description: null,
17
+ difficulty: null,
18
+ difficultyConvention: "europe" as any,
19
+ oneway: null,
20
+ lit: null,
21
+ gladed: null,
22
+ patrolled: null,
23
+ grooming: null,
24
+ skiAreas: [],
25
+ elevationProfile: null,
26
+ sources: [],
27
+ websites: [],
28
+ wikidata_id: null,
29
+ },
30
+ });
31
+
32
+ expect(getEstimatedRunDifficulty(0.03, downhillScale)).toBeNull(); // 3% steepness
33
+ });
34
+
35
+ it("should return correct difficulty for downhill slopes", () => {
36
+ const downhillScale = getSlopeGradingScale({
37
+ type: "Feature",
38
+ geometry: { type: "LineString", coordinates: [] },
39
+ properties: {
40
+ type: "Run" as any,
41
+ uses: [RunUse.Downhill],
42
+ id: "test",
43
+ name: null,
44
+ ref: null,
45
+ status: "operating" as any,
46
+ description: null,
47
+ difficulty: null,
48
+ difficultyConvention: "europe" as any,
49
+ oneway: null,
50
+ lit: null,
51
+ gladed: null,
52
+ patrolled: null,
53
+ grooming: null,
54
+ skiAreas: [],
55
+ elevationProfile: null,
56
+ sources: [],
57
+ websites: [],
58
+ wikidata_id: null,
59
+ },
60
+ });
61
+
62
+ expect(getEstimatedRunDifficulty(0.1, downhillScale)).toBe(RunDifficulty.EASY); // 10%
63
+ expect(getEstimatedRunDifficulty(0.3, downhillScale)).toBe(RunDifficulty.INTERMEDIATE); // 30%
64
+ expect(getEstimatedRunDifficulty(0.6, downhillScale)).toBe(RunDifficulty.ADVANCED); // 60%
65
+ expect(getEstimatedRunDifficulty(1.0, downhillScale)).toBe(RunDifficulty.EXPERT); // 100%
66
+ });
67
+
68
+ it("should return correct difficulty for nordic slopes", () => {
69
+ const nordicScale = getSlopeGradingScale({
70
+ type: "Feature",
71
+ geometry: { type: "LineString", coordinates: [] },
72
+ properties: {
73
+ type: "Run" as any,
74
+ uses: [RunUse.Nordic],
75
+ id: "test",
76
+ name: null,
77
+ ref: null,
78
+ status: "operating" as any,
79
+ description: null,
80
+ difficulty: null,
81
+ difficultyConvention: "europe" as any,
82
+ oneway: null,
83
+ lit: null,
84
+ gladed: null,
85
+ patrolled: null,
86
+ grooming: null,
87
+ skiAreas: [],
88
+ elevationProfile: null,
89
+ sources: [],
90
+ websites: [],
91
+ wikidata_id: null,
92
+ },
93
+ });
94
+
95
+ expect(getEstimatedRunDifficulty(0.05, nordicScale)).toBe(RunDifficulty.EASY); // 5%
96
+ expect(getEstimatedRunDifficulty(0.12, nordicScale)).toBe(RunDifficulty.INTERMEDIATE); // 12%
97
+ expect(getEstimatedRunDifficulty(0.25, nordicScale)).toBe(RunDifficulty.ADVANCED); // 25%
98
+ });
99
+
100
+ it("should handle negative steepness (uphill)", () => {
101
+ const downhillScale = getSlopeGradingScale({
102
+ type: "Feature",
103
+ geometry: { type: "LineString", coordinates: [] },
104
+ properties: {
105
+ type: "Run" as any,
106
+ uses: [RunUse.Downhill],
107
+ id: "test",
108
+ name: null,
109
+ ref: null,
110
+ status: "operating" as any,
111
+ description: null,
112
+ difficulty: null,
113
+ difficultyConvention: "europe" as any,
114
+ oneway: null,
115
+ lit: null,
116
+ gladed: null,
117
+ patrolled: null,
118
+ grooming: null,
119
+ skiAreas: [],
120
+ elevationProfile: null,
121
+ sources: [],
122
+ websites: [],
123
+ wikidata_id: null,
124
+ },
125
+ });
126
+
127
+ expect(getEstimatedRunDifficulty(-0.1, downhillScale)).toBe(RunDifficulty.EASY); // -10%
128
+ });
129
+ });