-
-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathAreaTypes.ts
More file actions
272 lines (248 loc) · 8.98 KB
/
AreaTypes.ts
File metadata and controls
272 lines (248 loc) · 8.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
import mongoose from 'mongoose'
import { MUUID } from 'uuid-mongodb'
import { BBox, Point, Polygon } from '@turf/helpers'
import { GradeContexts } from '../GradeUtils.js'
import { AuthorMetadata } from '../types.js'
import { ChangeRecordMetadataType } from './ChangeLogType.js'
import { ClimbType } from './ClimbTypes.js'
import { ExperimentalAuthorType } from './UserTypes.js'
export type AreaDocumnent = mongoose.Document<unknown, any, AreaType> & AreaType
/**
* Areas are a grouping mechanism in the OpenBeta data model that allow
* the organization of climbs into geospatial and hierarchical structures.
* Climbs are generally sorted by locals based on a set of area and sub-area
* structures. Beyond that, tourists are looking for climbs based on larger
* spaces not named and integrated by the climbing community. 'District', 'Region',
* 'City' would all be examples of this.
*
* In the OpenBeta data model, we treat 'Boulders' and 'Crags' as areas - albeit
* with distinct rules for how they are used
* (see leaf nodes https://docs.openbeta.io/how-to-contribute/contributing-data/areas)
*
* [more about area concepts](https://docs.openbeta.io/how-to-contribute/contributing-data/areas)
* */
export type AreaType = IAreaProps & {
metadata: IAreaMetadata
}
/**
* Properties that areas are expected to have.
* Objects of this kind may not be reified in the database and, if they are,
* they may be hard to locate based on the contents of this object.
* See AreaType for the reified version of this object, and always use it
* if you are working with data that exists inside the database.
*/
export interface IAreaProps extends AuthorMetadata {
_id: mongoose.Types.ObjectId
/**
* Area unique id (in UUID format). Same as `metadata.area_id`.
*/
uuid: MUUID
/**
* ShortCodes are short, globally uniqe codes that identify significant climbing areas
**/
shortCode?: string
/**
* What name is considered most popular for this area?
* Areas occasionally have multiple valid names, but this one is the one
* that might be considered as the 'most popular'.
*
* It's not a great idea to identify by this field, as area names are not
* unique and are subject to change.
**/
area_name: string
/**
* The climbs that appear within this area (Only applies for leaf nodes).
* Only areas that are permitted direct climb children will have these, and these
* are conventionally not allowed to have area children.
*/
climbs: Array<MUUID | ClimbType>
/**
* All child area documents that are contained within this area.
* This has a strong relation to the areas collection, and contains only direct
* child areas - rather than all descendents.
*/
children: mongoose.Types.ObjectId[]
/**
* ancestors ids of this areas parents, traversing up the heirarchy to the root area.
* This is encoded as a string, but is really an array delimited by comma.
* @see https://www.mongodb.com/docs/manual/tutorial/model-tree-structures-with-materialized-paths/
*/
ancestors: string
/**
* pathTokens names of this areas parents, traversing up the heirarchy to the root area
* with the current area being the last element.
*/
pathTokens: string[]
gradeContext: GradeContexts
/**
* computed aggregations on this document. See the AggregateType documentation for
* more information.
*/
aggregate: AggregateType
/**
* User-composed content that makes up most of the user-readable data in the system.
* See the IAreaContent documentation for more information.
**/
content: IAreaContent
/**
* how many climbs are in this area per square kilometer.
* This field is re-computed on its own schedule, but is not guaranteed to
* be accurate for a given system state. It depends on the size of the area,
* and the implementation of the update system in play.
* */
density: number
/**
* The total number of climbs in this area, regardless of hierarchy depth.
* Meaning that for a country, even though the document may not contain any
* direct children
* */
/** The total number of climbs in this area. */
totalClimbs: number
/**
* If this area has been edited, this field will contain the metadata about the
* last edit that was made.
*/
_change?: ChangeRecordMetadataType
/** Used to delete an area. See https://www.mongodb.com/docs/manual/core/index-ttl/ */
_deleting?: Date
}
export interface IAreaMetadata {
isDestination: boolean
/**
* Leaf areas may have climbs as children, but may not have other areas as children.
**/
leaf: boolean
/**
* Some contributions will create areas that may not immediately have any climbs,
* but are nevertheless intended as leaf nodes that should contain primarily bouldering
* climbs, but definitely ONLY climbs.
*
* If not set, but the area is a leaf node, we expect that the area may be a crag(cliff)
* and will contain largely sport and trad climbs.
*/
isBoulder?: boolean
/**
* Location of a wall or a boulder aka leaf node. Use `bbox` or `polygon` non-leaf areas.
* */
lnglat?: Point
/**
* The smallest possible bounding box (northwest and southeast coordinates) that contains
* all of this areas children (Both sub-areas and climbs).
*/
bbox?: BBox
/**
* Left-to-right sorting index. Undefined or -1 for unsorted area,
*/
leftRightIndex?: number
/**
* Some areas have been directly imported into the OpenBeta dataset, and if they have
* this field will record their external relation.
* */
ext_id?: string
/**
* Some areas have an identifier on https://www.wikidata.org
* This identifier matches the regex `^Q\d+$`
* */
wikidata_id?: string
/**
* All external IDs for areas are expressed as UUIDs. As such, when resolving ids at the
* GQL layer use these values for querying and identification of areas.
*/
area_id: MUUID
/**
* A polygon (created by convex hull) containing all child areas.
*/
polygon?: Polygon
}
export interface IAreaContent {
/** longform to mediumform description and location of this area.
* Remembering that area descriptions can be the size of countries, or as precise as a single cliff/boulder,
* there is not a single definition of valid content for this field.
*
* We expect users to make a call about whatever kind of context may be appropriate for this
* entity, and may be pretty short to extremely detailed.
*/
description?: string
areaLocation?: string
}
/** Fields that may be directly modified by users.
* This does not define the total set of mutable fields in the area, only the ones that users
* may directly submit and over-write.
*/
export interface AreaEditableFieldsType {
areaName?: string
description?: string
areaLocation?: string
isDestination?: boolean
isLeaf?: boolean
isBoulder?: boolean
shortCode?: string
lat?: number
lng?: number
leftRightIndex?: number
experimentalAuthor?: ExperimentalAuthorType
}
export type UpdateSortingOrderType = {
areaId: string
} & Required<Pick<AreaEditableFieldsType, 'leftRightIndex'>>
export interface CountByGroupType {
count: number
label: string
}
export interface AggregateType {
byGrade: CountByGroupType[]
byDiscipline: CountByDisciplineType
byGradeBand: CountByGradeBandType
}
export interface CountByDisciplineType {
trad?: DisciplineStatsType
sport?: DisciplineStatsType
bouldering?: DisciplineStatsType
deepwatersolo?: DisciplineStatsType
alpine?: DisciplineStatsType
snow?: DisciplineStatsType
ice?: DisciplineStatsType
mixed?: DisciplineStatsType
aid?: DisciplineStatsType
tr?: DisciplineStatsType
}
export interface DisciplineStatsType {
total: number
bands: CountByGradeBandType
}
/** Aggreation type counting grade bands, which are a meta grading system */
export interface CountByGradeBandType {
unknown: number
beginner: number
intermediate: number
advanced: number
expert: number
}
/** The audit trail comprises a set of controlled events that may occur in relation
* to user action on core data. The enumeration herein defines the set of events
* that may occur, and short documentation of what they mean
*/
export enum OperationType {
/** The addition of countries is a pretty big deal, as we expect most countries to
* already be added - and this event is only expected to occur once per country.
*/
addCountry = 'addCountry',
/** Signal meaning that an area has been created in the areas collection */
addArea = 'addArea',
/**
* This event signals that an area should be deleted. These signals can be reversed,
* areas being capable of un-deletion.
*/
deleteArea = 'deleteArea',
/** see metadata.isDestination for more information, this signals a change in this
* specific field's boolean state.
*/
updateDestination = 'updateDestination',
/** signals that a user has pushed new user-changeable data has been pushed into an area document. */
updateArea = 'updateArea',
/** Set areas' sorting index */
orderAreas = 'orderArea'
}
export interface BulkAreasGQLQueryInput {
ancestors: string[]
}