coh-content-db 2.0.0-rc.6 → 2.0.0-rc.7

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.
Files changed (65) hide show
  1. package/README.md +3 -3
  2. package/dist/coh-content-db.d.ts +384 -181
  3. package/dist/coh-content-db.js +604 -348
  4. package/dist/coh-content-db.js.map +1 -1
  5. package/dist/coh-content-db.mjs +592 -347
  6. package/dist/coh-content-db.mjs.map +1 -1
  7. package/eslint.config.mjs +1 -0
  8. package/package.json +1 -1
  9. package/src/main/api/alignment.ts +18 -2
  10. package/src/main/api/badge-data.ts +12 -42
  11. package/src/main/api/badge-requirement-data.ts +17 -35
  12. package/src/main/api/badge-requirement-type.ts +28 -7
  13. package/src/main/api/badge-type.ts +15 -15
  14. package/src/main/api/contact-data.ts +7 -5
  15. package/src/main/api/content-bundle.ts +6 -0
  16. package/src/main/api/enhancement-category.ts +26 -26
  17. package/src/main/api/location-data.ts +28 -0
  18. package/src/main/api/mission-data.ts +83 -0
  19. package/src/main/api/mission-type.ts +2 -0
  20. package/src/main/api/morality.ts +31 -0
  21. package/src/main/api/sex.ts +8 -1
  22. package/src/main/api/zone-data.ts +1 -1
  23. package/src/main/changelog.ts +5 -4
  24. package/src/main/db/alignment-list.ts +54 -0
  25. package/src/main/db/alternates.ts +15 -32
  26. package/src/main/db/badge-index.ts +11 -36
  27. package/src/main/db/badge-requirement.ts +22 -43
  28. package/src/main/db/badge-search-options.ts +4 -4
  29. package/src/main/db/badge.ts +53 -54
  30. package/src/main/db/coh-content-database.ts +28 -24
  31. package/src/main/db/contact.ts +17 -14
  32. package/src/main/db/location.ts +30 -0
  33. package/src/main/db/mission.ts +107 -0
  34. package/src/main/db/morality-list.ts +99 -0
  35. package/src/main/db/zone.ts +1 -1
  36. package/src/main/index.ts +8 -3
  37. package/src/main/util.ts +43 -3
  38. package/src/test/api/alignment.test.ts +38 -4
  39. package/src/test/api/badge-data.fixture.ts +1 -17
  40. package/src/test/api/badge-data.test.ts +3 -3
  41. package/src/test/api/badge-requirement-data.fixture.ts +1 -11
  42. package/src/test/api/badge-requirement-type.test.ts +3 -3
  43. package/src/test/api/badge-type.test.ts +5 -5
  44. package/src/test/api/contact-data.fixture.ts +0 -6
  45. package/src/test/api/content-bundle.fixture.ts +1 -17
  46. package/src/test/api/enhancement-category.test.ts +5 -5
  47. package/src/test/api/mission-data.fixture.ts +12 -0
  48. package/src/test/api/sex.test.ts +33 -1
  49. package/src/test/api/zone-data.fixture.ts +1 -1
  50. package/src/test/db/alignment-list.test.ts +200 -0
  51. package/src/test/db/alternates.test.ts +60 -56
  52. package/src/test/db/badge-index.test.ts +82 -72
  53. package/src/test/db/badge-requirement.test.ts +35 -70
  54. package/src/test/db/badge.test.ts +185 -64
  55. package/src/test/db/coh-content-database.test.ts +58 -69
  56. package/src/test/db/contact.test.ts +25 -24
  57. package/src/test/db/location.test.ts +51 -0
  58. package/src/test/db/mission.test.ts +171 -0
  59. package/src/test/db/morality-list.test.ts +457 -0
  60. package/src/test/db/zone.test.ts +4 -4
  61. package/src/test/util.test.ts +54 -1
  62. package/src/main/api/plaque-type.ts +0 -6
  63. package/src/main/db/alignments.ts +0 -17
  64. package/src/test/api/alignments.test.ts +0 -40
  65. package/src/test/api/plaque-type.test.ts +0 -31
@@ -6,11 +6,15 @@ describe(Alternates.name, () => {
6
6
  new Alternates([
7
7
  { value: 'Default' },
8
8
  { sex: 'M', value: 'Male' },
9
- { alignment: 'H', value: 'Hero' },
10
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
11
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
9
+ { alignment: 'hero', value: 'Hero' },
10
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
11
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
12
12
  ])
13
13
  })
14
+
15
+ test('should accept a single value', () => {
16
+ expect(new Alternates('foo').default?.value).toBe('foo')
17
+ })
14
18
  })
15
19
 
16
20
  describe('getValue', () => {
@@ -22,19 +26,19 @@ describe(Alternates.name, () => {
22
26
  expect(new Alternates([
23
27
  { value: 'Default' },
24
28
  { sex: 'M', value: 'Male' },
25
- { alignment: 'H', value: 'Hero' },
26
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
27
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
29
+ { alignment: 'hero', value: 'Hero' },
30
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
31
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
28
32
  ]).getValue()).toBe('Default')
29
33
  })
30
34
 
31
35
  test('should return the least-specific value when no classifiers are provided, regardless of insert order', () => {
32
36
  expect(new Alternates([
33
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
34
- { alignment: 'H', value: 'Hero' },
37
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
38
+ { alignment: 'hero', value: 'Hero' },
35
39
  { value: 'Default' },
36
40
  { sex: 'M', value: 'Male' },
37
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
41
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
38
42
  ]).getValue()).toBe('Default')
39
43
  })
40
44
 
@@ -42,37 +46,37 @@ describe(Alternates.name, () => {
42
46
  expect(new Alternates([
43
47
  { value: 'Default' },
44
48
  { sex: 'M', value: 'Male' },
45
- { alignment: 'H', value: 'Hero' },
46
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
47
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
48
- ]).getValue('V', 'M')).toBe('Male Villain')
49
+ { alignment: 'hero', value: 'Hero' },
50
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
51
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
52
+ ]).getValue('villain', 'M')).toBe('Male Villain')
49
53
  })
50
54
 
51
55
  test('should return the most specific match, regardless of insert order', () => {
52
56
  expect(new Alternates([
53
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
57
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
54
58
  { sex: 'M', value: 'Male' },
55
- { alignment: 'H', value: 'Hero' },
56
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
59
+ { alignment: 'hero', value: 'Hero' },
60
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
57
61
  { value: 'Default' },
58
- ]).getValue('V', 'M')).toBe('Male Villain')
62
+ ]).getValue('villain', 'M')).toBe('Male Villain')
59
63
  })
60
64
 
61
65
  test('should return the lowest canonical value if there is no default', () => {
62
66
  expect(new Alternates([
63
- { alignment: 'H', value: 'Hero' },
67
+ { alignment: 'hero', value: 'Hero' },
64
68
  { sex: 'M', value: 'Male' },
65
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
66
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
69
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
70
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
67
71
  ]).getValue()).toBe('Male')
68
72
  })
69
73
 
70
74
  test('should return the lowest canonical value if a specific is requested that does not exist', () => {
71
75
  expect(new Alternates([
72
- { alignment: 'H', value: 'Hero' },
73
- { alignment: 'V', value: 'Villain' },
74
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
75
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
76
+ { alignment: 'hero', value: 'Hero' },
77
+ { alignment: 'villain', value: 'Villain' },
78
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
79
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
76
80
  ]).getValue(undefined, 'F')).toBe('Hero')
77
81
  })
78
82
  })
@@ -86,24 +90,24 @@ describe(Alternates.name, () => {
86
90
  expect(new Alternates([
87
91
  { value: 'Default' },
88
92
  { sex: 'M', value: 'Male' },
89
- { alignment: 'H', value: 'Hero' },
90
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
91
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
93
+ { alignment: 'hero', value: 'Hero' },
94
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
95
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
92
96
  ]).default?.value).toBe('Default')
93
97
 
94
98
  expect(new Alternates([
95
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
96
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
99
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
100
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
97
101
  { sex: 'M', value: 'Male' },
98
102
  { value: 'Default' },
99
- { alignment: 'H', value: 'Hero' },
103
+ { alignment: 'hero', value: 'Hero' },
100
104
  ]).default?.value).toBe('Default')
101
105
 
102
106
  expect(new Alternates([
103
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
104
- { alignment: 'P', sex: 'F', value: 'Praetorian Female' },
107
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
108
+ { alignment: 'praetorian', sex: 'F', value: 'Praetorian Female' },
105
109
  { sex: 'M', value: 'Male' },
106
- { alignment: 'H', value: 'Hero' },
110
+ { alignment: 'hero', value: 'Hero' },
107
111
  ]).default?.value).toBe('Male')
108
112
  })
109
113
  })
@@ -115,17 +119,17 @@ describe(Alternates.name, () => {
115
119
 
116
120
  test('should return values sorted in canonical order', () => {
117
121
  const result = new Alternates([
118
- { alignment: 'H', sex: 'F', value: 'Female Hero' },
119
- { alignment: 'P', value: 'Praetorian' },
122
+ { alignment: 'hero', sex: 'F', value: 'Female Hero' },
123
+ { alignment: 'praetorian', value: 'Praetorian' },
120
124
  { sex: 'F', value: 'Female' },
121
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
122
- { alignment: 'P', sex: 'M', value: 'Male Praetorian' },
123
- { alignment: 'H', value: 'Hero' },
124
- { alignment: 'H', sex: 'M', value: 'Male Hero' },
125
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
126
+ { alignment: 'praetorian', sex: 'M', value: 'Male Praetorian' },
127
+ { alignment: 'hero', value: 'Hero' },
128
+ { alignment: 'hero', sex: 'M', value: 'Male Hero' },
125
129
  { sex: 'M', value: 'Male' },
126
- { alignment: 'V', value: 'Villain' },
127
- { alignment: 'V', sex: 'F', value: 'Female Villain' },
128
- { alignment: 'P', sex: 'F', value: 'Female Praetorian' },
130
+ { alignment: 'villain', value: 'Villain' },
131
+ { alignment: 'villain', sex: 'F', value: 'Female Villain' },
132
+ { alignment: 'praetorian', sex: 'F', value: 'Female Praetorian' },
129
133
  { value: 'Default' },
130
134
  ]).canonical
131
135
 
@@ -133,15 +137,15 @@ describe(Alternates.name, () => {
133
137
  { value: 'Default' },
134
138
  { sex: 'M', value: 'Male' },
135
139
  { sex: 'F', value: 'Female' },
136
- { alignment: 'H', value: 'Hero' },
137
- { alignment: 'V', value: 'Villain' },
138
- { alignment: 'P', value: 'Praetorian' },
139
- { alignment: 'H', sex: 'M', value: 'Male Hero' },
140
- { alignment: 'H', sex: 'F', value: 'Female Hero' },
141
- { alignment: 'V', sex: 'M', value: 'Male Villain' },
142
- { alignment: 'V', sex: 'F', value: 'Female Villain' },
143
- { alignment: 'P', sex: 'M', value: 'Male Praetorian' },
144
- { alignment: 'P', sex: 'F', value: 'Female Praetorian' },
140
+ { alignment: 'hero', value: 'Hero' },
141
+ { alignment: 'villain', value: 'Villain' },
142
+ { alignment: 'praetorian', value: 'Praetorian' },
143
+ { alignment: 'hero', sex: 'M', value: 'Male Hero' },
144
+ { alignment: 'hero', sex: 'F', value: 'Female Hero' },
145
+ { alignment: 'villain', sex: 'M', value: 'Male Villain' },
146
+ { alignment: 'villain', sex: 'F', value: 'Female Villain' },
147
+ { alignment: 'praetorian', sex: 'M', value: 'Male Praetorian' },
148
+ { alignment: 'praetorian', sex: 'F', value: 'Female Praetorian' },
145
149
  ])
146
150
  })
147
151
 
@@ -159,15 +163,15 @@ describe(Alternates.name, () => {
159
163
 
160
164
  test('should sort identical values by value alpha', () => {
161
165
  expect(new Alternates([
162
- { alignment: 'V', value: 'B' },
166
+ { alignment: 'villain', value: 'B' },
163
167
  { sex: 'M', value: 'D' },
164
- { alignment: 'V', value: 'A' },
168
+ { alignment: 'villain', value: 'A' },
165
169
  { sex: 'M', value: 'C' },
166
170
  ]).canonical).toStrictEqual([
167
171
  { sex: 'M', value: 'C' },
168
172
  { sex: 'M', value: 'D' },
169
- { alignment: 'V', value: 'A' },
170
- { alignment: 'V', value: 'B' },
173
+ { alignment: 'villain', value: 'A' },
174
+ { alignment: 'villain', value: 'B' },
171
175
  ])
172
176
  })
173
177
  })
@@ -177,7 +181,7 @@ describe(Alternates.name, () => {
177
181
  expect(new Alternates([
178
182
  { sex: 'M', value: 'A' },
179
183
  { sex: 'F', value: 'B' },
180
- { alignment: 'H', value: 'C' },
184
+ { alignment: 'hero', value: 'C' },
181
185
  ]).toString(', ')).toBe('A, B, C')
182
186
  })
183
187
  })
@@ -1,12 +1,6 @@
1
1
  import { badgeDataFixture } from '../api/badge-data.fixture'
2
- import { Badge, BadgeIndex, Zone } from '../../main'
3
- import { zoneDataFixture } from '../api/zone-data.fixture'
4
-
5
- const TEST_Zones = [
6
- new Zone(zoneDataFixture.create({ key: 'atlas-park', name: 'Atlas Park' })),
7
- new Zone(zoneDataFixture.create({ key: 'perez-park', name: 'Perez Park' })),
8
- new Zone(zoneDataFixture.create({ key: 'abandoned-sewer-network', name: 'Abandoned Sewer Network' })),
9
- ]
2
+ import { Badge, BadgeIndex } from '../../main'
3
+ import { badgeRequirementDataFixture } from '../api/badge-requirement-data.fixture'
10
4
 
11
5
  describe(BadgeIndex.name, () => {
12
6
  describe('Constructor', () => {
@@ -26,20 +20,12 @@ describe(BadgeIndex.name, () => {
26
20
  expect(new BadgeIndex(data).getBadge('foo')).not.toBeUndefined()
27
21
  })
28
22
 
29
- test(`should throw error for unknown badge`, () => {
30
- expect(() => new BadgeIndex([]).getBadge('foo')).toThrow('Unknown badge key [foo]')
31
- })
32
- })
33
-
34
- describe('badgeExists', () => {
35
- test(`should return true for a badge that exists`, () => {
36
- const data = [new Badge(badgeDataFixture.create({ key: 'foo' }))]
37
-
38
- expect(new BadgeIndex(data).badgeExists('foo')).toBeTruthy()
23
+ test(`should return undefined for unknown badge`, () => {
24
+ expect(new BadgeIndex([]).getBadge('foo')).toBeUndefined()
39
25
  })
40
26
 
41
- test(`should return false for a badge that does not exist`, () => {
42
- expect(new BadgeIndex([]).badgeExists('foo')).toBeFalsy()
27
+ test(`should return undefined for undefined key`, () => {
28
+ expect(new BadgeIndex([]).getBadge()).toBeUndefined()
43
29
  })
44
30
  })
45
31
 
@@ -128,10 +114,10 @@ describe(BadgeIndex.name, () => {
128
114
 
129
115
  test(`should match on setTitle`, () => {
130
116
  const data = [
131
- new Badge(badgeDataFixture.create({ key: 'match-1', setTitle: { id: 123 } })),
132
- new Badge(badgeDataFixture.create({ key: 'match-2', setTitle: { id: 456, praetorianId: 123 } })),
133
- new Badge(badgeDataFixture.create({ key: 'miss-1', setTitle: { id: 456 } })),
134
- new Badge(badgeDataFixture.create({ key: 'miss-2', setTitle: undefined })),
117
+ new Badge(badgeDataFixture.create({ key: 'match-1', setTitleId: [123] })),
118
+ new Badge(badgeDataFixture.create({ key: 'match-2', setTitleId: [456, 123] })),
119
+ new Badge(badgeDataFixture.create({ key: 'miss-1', setTitleId: [456] })),
120
+ new Badge(badgeDataFixture.create({ key: 'miss-2', setTitleId: undefined })),
135
121
  ]
136
122
 
137
123
  const result = new BadgeIndex(data).searchBadges({ query: { str: '123', on: { setTitle: true } } })
@@ -197,45 +183,50 @@ describe(BadgeIndex.name, () => {
197
183
 
198
184
  test(`should filter on badge type`, () => {
199
185
  const data = [
200
- new Badge(badgeDataFixture.create({ key: 'badge-1', type: 'EXPLORATION' })),
201
- new Badge(badgeDataFixture.create({ key: 'badge-2', type: 'EXPLORATION' })),
202
- new Badge(badgeDataFixture.create({ key: 'badge-3', type: 'HISTORY' })),
203
- new Badge(badgeDataFixture.create({ key: 'badge-4', type: 'HISTORY' })),
204
- new Badge(badgeDataFixture.create({ key: 'badge-5', type: 'ACCOLADE' })),
205
- new Badge(badgeDataFixture.create({ key: 'badge-6', type: 'ACCOLADE' })),
186
+ new Badge(badgeDataFixture.create({ key: 'badge-1', type: 'exploration' })),
187
+ new Badge(badgeDataFixture.create({ key: 'badge-2', type: 'exploration' })),
188
+ new Badge(badgeDataFixture.create({ key: 'badge-3', type: 'history' })),
189
+ new Badge(badgeDataFixture.create({ key: 'badge-4', type: 'history' })),
190
+ new Badge(badgeDataFixture.create({ key: 'badge-5', type: 'accolade' })),
191
+ new Badge(badgeDataFixture.create({ key: 'badge-6', type: 'accolade' })),
206
192
  ]
207
193
 
208
- const result = new BadgeIndex(data).searchBadges({ filter: { type: 'HISTORY' } })
194
+ const result = new BadgeIndex(data).searchBadges({ filter: { type: 'history' } })
209
195
  const keys = result.items.map(x => x.key)
210
196
  expect(keys).toStrictEqual(['badge-3', 'badge-4'])
211
197
  })
212
198
 
213
- test(`should filter on badge type`, () => {
199
+ test(`should filter on badge zone`, () => {
214
200
  const data = [
215
- new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
216
- new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
217
- new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'abandoned-sewer-network' })),
218
- new Badge(badgeDataFixture.create({ key: 'badge-4', zoneKey: 'atlas-park' })),
219
- new Badge(badgeDataFixture.create({ key: 'badge-5', zoneKey: 'perez-park' })),
220
- new Badge(badgeDataFixture.create({ key: 'badge-6', zoneKey: undefined })),
201
+ new Badge(badgeDataFixture.create({ key: 'badge-1', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
202
+ new Badge(badgeDataFixture.create({ key: 'badge-2', requirements: [{ location: { zoneKey: 'perez-park' } }] })),
203
+ new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
204
+ new Badge(badgeDataFixture.create({ key: 'badge-4', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
205
+ new Badge(badgeDataFixture.create({
206
+ key: 'badge-5', requirements: [
207
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'atlas-park' } }),
208
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'perez-park' } }),
209
+ ],
210
+ })),
211
+ new Badge(badgeDataFixture.create({ key: 'badge-6', requirements: [{ location: undefined }] })),
221
212
  ]
222
213
 
223
214
  const result = new BadgeIndex(data).searchBadges({ filter: { zoneKey: 'perez-park' } })
224
215
  const keys = result.items.map(x => x.key)
225
- expect(keys).toStrictEqual(['badge-2', 'badge-5'])
216
+ expect(keys).toStrictEqual(['badge-2'])
226
217
  })
227
218
 
228
- test(`should filter on badge type`, () => {
219
+ test(`should filter on alignment`, () => {
229
220
  const data = [
230
- new Badge(badgeDataFixture.create({ key: 'badge-1', alignment: ['H'] })),
231
- new Badge(badgeDataFixture.create({ key: 'badge-2', alignment: ['V'] })),
232
- new Badge(badgeDataFixture.create({ key: 'badge-3', alignment: ['P'] })),
233
- new Badge(badgeDataFixture.create({ key: 'badge-4', alignment: ['H', 'V'] })),
234
- new Badge(badgeDataFixture.create({ key: 'badge-5', alignment: ['V', 'P'] })),
235
- new Badge(badgeDataFixture.create({ key: 'badge-6', alignment: ['H', 'V', 'P'] })),
221
+ new Badge(badgeDataFixture.create({ key: 'badge-1', morality: ['hero'] })),
222
+ new Badge(badgeDataFixture.create({ key: 'badge-2', morality: ['villain'] })),
223
+ new Badge(badgeDataFixture.create({ key: 'badge-3', morality: ['loyalist'] })),
224
+ new Badge(badgeDataFixture.create({ key: 'badge-4', morality: ['hero', 'villain'] })),
225
+ new Badge(badgeDataFixture.create({ key: 'badge-5', morality: ['villain', 'loyalist'] })),
226
+ new Badge(badgeDataFixture.create({ key: 'badge-6', morality: ['hero', 'villain', 'loyalist'] })),
236
227
  ]
237
228
 
238
- const result = new BadgeIndex(data).searchBadges({ filter: { alignment: 'H' } })
229
+ const result = new BadgeIndex(data).searchBadges({ filter: { morality: 'hero' } })
239
230
  const keys = result.items.map(x => x.key)
240
231
  expect(keys).toStrictEqual(['badge-1', 'badge-4', 'badge-6'])
241
232
  })
@@ -402,7 +393,21 @@ describe(BadgeIndex.name, () => {
402
393
  new Badge(badgeDataFixture.create({ key: 'badge-4' })),
403
394
  ]
404
395
 
405
- const result = new BadgeIndex(data, TEST_Zones).searchBadges()
396
+ const result = new BadgeIndex(data).searchBadges()
397
+
398
+ const keys = result.items.map(x => x.key)
399
+ expect(keys).toStrictEqual(['badge-1', 'badge-2', 'badge-3', 'badge-4'])
400
+ })
401
+
402
+ test(`should not modify sort if order is canonical`, () => {
403
+ const data = [
404
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
405
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
406
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
407
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
408
+ ]
409
+
410
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'canonical' } })
406
411
 
407
412
  const keys = result.items.map(x => x.key)
408
413
  expect(keys).toStrictEqual(['badge-1', 'badge-2', 'badge-3', 'badge-4'])
@@ -416,7 +421,7 @@ describe(BadgeIndex.name, () => {
416
421
  new Badge(badgeDataFixture.create({ key: 'badge-4' })),
417
422
  ]
418
423
 
419
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { dir: 'DESC' } })
424
+ const result = new BadgeIndex(data).searchBadges({ sort: { dir: 'desc' } })
420
425
 
421
426
  const keys = result.items.map(x => x.key)
422
427
  expect(keys).toStrictEqual(['badge-4', 'badge-3', 'badge-2', 'badge-1'])
@@ -429,7 +434,7 @@ describe(BadgeIndex.name, () => {
429
434
  new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
430
435
  ]
431
436
 
432
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'BADGE_NAME' } })
437
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'badge-name' } })
433
438
 
434
439
  const keys = result.items.map(x => x.key)
435
440
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
@@ -442,7 +447,7 @@ describe(BadgeIndex.name, () => {
442
447
  new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
443
448
  ]
444
449
 
445
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'BADGE_NAME', dir: 'DESC' } })
450
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'badge-name', dir: 'desc' } })
446
451
 
447
452
  const keys = result.items.map(x => x.key)
448
453
  expect(keys).toStrictEqual(['badge-2', 'badge-1', 'badge-3'])
@@ -455,7 +460,7 @@ describe(BadgeIndex.name, () => {
455
460
  new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
456
461
  ]
457
462
 
458
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'BADGE_NAME' } })
463
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'badge-name' } })
459
464
 
460
465
  const keys = result.items.map(x => x.key)
461
466
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
@@ -463,12 +468,12 @@ describe(BadgeIndex.name, () => {
463
468
 
464
469
  test(`should sort by zone name`, () => {
465
470
  const data = [
466
- new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
467
- new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
468
- new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'abandoned-sewer-network' })),
471
+ new Badge(badgeDataFixture.create({ key: 'badge-1', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
472
+ new Badge(badgeDataFixture.create({ key: 'badge-2', requirements: [{ location: { zoneKey: 'perez-park' } }] })),
473
+ new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
469
474
  ]
470
475
 
471
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME' } })
476
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'zone-key' } })
472
477
 
473
478
  const keys = result.items.map(x => x.key)
474
479
  expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
@@ -476,12 +481,12 @@ describe(BadgeIndex.name, () => {
476
481
 
477
482
  test(`should sort by zone name descending`, () => {
478
483
  const data = [
479
- new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
480
- new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
481
- new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'abandoned-sewer-network' })),
484
+ new Badge(badgeDataFixture.create({ key: 'badge-1', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
485
+ new Badge(badgeDataFixture.create({ key: 'badge-2', requirements: [{ location: { zoneKey: 'perez-park' } }] })),
486
+ new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
482
487
  ]
483
488
 
484
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME', dir: 'DESC' } })
489
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'zone-key', dir: 'desc' } })
485
490
 
486
491
  const keys = result.items.map(x => x.key)
487
492
  expect(keys).toStrictEqual(['badge-2', 'badge-1', 'badge-3'])
@@ -489,28 +494,33 @@ describe(BadgeIndex.name, () => {
489
494
 
490
495
  test(`should maintain canonical as secondary sort when sorting by zone name`, () => {
491
496
  const data = [
492
- new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
493
- new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
494
- new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'atlas-park' })),
495
- new Badge(badgeDataFixture.create({ key: 'badge-4', zoneKey: 'abandoned-sewer-network' })),
497
+ new Badge(badgeDataFixture.create({ key: 'badge-1', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
498
+ new Badge(badgeDataFixture.create({ key: 'badge-2', requirements: [{ location: { zoneKey: 'perez-park' } }] })),
499
+ new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
500
+ new Badge(badgeDataFixture.create({ key: 'badge-4', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
496
501
  ]
497
502
 
498
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME' } })
503
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'zone-key' } })
499
504
 
500
505
  const keys = result.items.map(x => x.key)
501
506
  expect(keys).toStrictEqual(['badge-4', 'badge-1', 'badge-3', 'badge-2'])
502
507
  })
503
508
 
504
- test(`should sort unknown zone names to the end`, () => {
509
+ test(`should sort undefined or multiple zone names to the end`, () => {
505
510
  const data = [
506
- new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
507
- new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'unknown' })),
508
- new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'perez-park' })),
509
- new Badge(badgeDataFixture.create({ key: 'badge-4', zoneKey: 'unexpected' })),
510
- new Badge(badgeDataFixture.create({ key: 'badge-5', zoneKey: 'abandoned-sewer-network' })),
511
+ new Badge(badgeDataFixture.create({ key: 'badge-1', requirements: [{ location: { zoneKey: 'atlas-park' } }] })),
512
+ new Badge(badgeDataFixture.create({ key: 'badge-2', requirements: [{ location: undefined }] })),
513
+ new Badge(badgeDataFixture.create({ key: 'badge-3', requirements: [{ location: { zoneKey: 'perez-park' } }] })),
514
+ new Badge(badgeDataFixture.create({
515
+ key: 'badge-4', requirements: [
516
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'atlas-park' } }),
517
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'perez-park' } }),
518
+ ],
519
+ })),
520
+ new Badge(badgeDataFixture.create({ key: 'badge-5', requirements: [{ location: { zoneKey: 'abandoned-sewer-network' } }] })),
511
521
  ]
512
522
 
513
- const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME' } })
523
+ const result = new BadgeIndex(data).searchBadges({ sort: { by: 'zone-key' } })
514
524
 
515
525
  const keys = result.items.map(x => x.key)
516
526
  expect(keys).toStrictEqual(['badge-5', 'badge-1', 'badge-3', 'badge-2', 'badge-4'])
@@ -17,68 +17,33 @@ describe(BadgeRequirement.name, () => {
17
17
 
18
18
  describe('type', () => {
19
19
  test('should be set from the data', () => {
20
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ type: 'BADGE' }))
21
- expect(requirement.type).toEqual('BADGE')
20
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ type: 'badge' }))
21
+ expect(requirement.type).toEqual('badge')
22
22
  })
23
23
  })
24
24
 
25
- describe('zoneKey', () => {
25
+ describe('location', () => {
26
26
  test('should be set from the data', () => {
27
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ zoneKey: 'zone123' }))
28
- expect(requirement.zoneKey).toEqual('zone123')
27
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ location: { zoneKey: 'foo', coords: [1, 2, 3] } }))
28
+ expect(requirement.location).toStrictEqual([{ zoneKey: 'foo', coords: [1, 2, 3] }])
29
29
  })
30
30
 
31
- test('should be optional', () => {
32
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('zoneKey').create())
33
- expect(requirement.zoneKey).toBeUndefined()
34
- })
35
- })
36
-
37
- describe('loc', () => {
38
- test('should be set from the data', () => {
39
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ loc: [1, 2, 3] }))
40
- expect(requirement.loc).toStrictEqual([1, 2, 3])
41
- })
42
-
43
- test('should be optional', () => {
44
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('loc').create())
45
- expect(requirement.loc).toBeUndefined()
46
- })
47
- })
48
-
49
- describe('plaqueType', () => {
50
- test('should be set from the data', () => {
51
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ plaqueType: 'MONUMENT' }))
52
- expect(requirement.plaqueType).toEqual('MONUMENT')
53
- })
54
-
55
- test('should be optional', () => {
56
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('plaqueType').create())
57
- expect(requirement.plaqueType).toBeUndefined()
58
- })
59
- })
60
-
61
- describe('plaqueInscription', () => {
62
- test('should be set from the data', () => {
63
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ plaqueInscription: 'foo' }))
64
- expect(requirement.plaqueInscription).toEqual('foo')
65
- })
66
-
67
- test('should be optional', () => {
68
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('plaqueInscription').create())
69
- expect(requirement.plaqueInscription).toBeUndefined()
70
- })
71
- })
72
-
73
- describe('vidiotMapKey', () => {
74
- test('should be set from the data', () => {
75
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ vidiotMapKey: 'A1' }))
76
- expect(requirement.vidiotMapKey).toEqual('A1')
31
+ test('should accept an array', () => {
32
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({
33
+ location: [
34
+ { zoneKey: 'foo', coords: [1, 2, 3] },
35
+ { zoneKey: 'bar', coords: [4, 5, 6] },
36
+ ],
37
+ }))
38
+ expect(requirement.location).toStrictEqual([
39
+ { zoneKey: 'foo', coords: [1, 2, 3] },
40
+ { zoneKey: 'bar', coords: [4, 5, 6] },
41
+ ])
77
42
  })
78
43
 
79
44
  test('should be optional', () => {
80
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('vidiotMapKey').create())
81
- expect(requirement.vidiotMapKey).toBeUndefined()
45
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('location').create())
46
+ expect(requirement.location).toBeUndefined()
82
47
  })
83
48
  })
84
49
 
@@ -94,27 +59,27 @@ describe(BadgeRequirement.name, () => {
94
59
  })
95
60
  })
96
61
 
97
- describe('missionName', () => {
62
+ describe('missionKey', () => {
98
63
  test('should be set from the data', () => {
99
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ missionName: 'foo' }))
100
- expect(requirement.missionName).toEqual('foo')
64
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ missionKey: 'foo' }))
65
+ expect(requirement.missionKey).toEqual('foo')
101
66
  })
102
67
 
103
68
  test('should be optional', () => {
104
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('missionName').create())
105
- expect(requirement.missionName).toBeUndefined()
69
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('missionKey').create())
70
+ expect(requirement.missionKey).toBeUndefined()
106
71
  })
107
72
  })
108
73
 
109
- describe('contactKey', () => {
74
+ describe('monumentText', () => {
110
75
  test('should be set from the data', () => {
111
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ contactKey: 'foo' }))
112
- expect(requirement.contactKey).toEqual('foo')
76
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ monumentText: 'foo' }))
77
+ expect(requirement.monumentText).toEqual('foo')
113
78
  })
114
79
 
115
80
  test('should be optional', () => {
116
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('contactKey').create())
117
- expect(requirement.contactKey).toBeUndefined()
81
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('monumentText').create())
82
+ expect(requirement.monumentText).toBeUndefined()
118
83
  })
119
84
  })
120
85
 
@@ -132,8 +97,8 @@ describe(BadgeRequirement.name, () => {
132
97
 
133
98
  describe('inventionTypes', () => {
134
99
  test('should be set from the data', () => {
135
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ inventionTypes: ['ACCURACY', 'CONFUSE'] }))
136
- expect(requirement.inventionTypes).toStrictEqual(['ACCURACY', 'CONFUSE'])
100
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ inventionTypes: ['accuracy', 'confuse'] }))
101
+ expect(requirement.inventionTypes).toStrictEqual(['accuracy', 'confuse'])
137
102
  })
138
103
 
139
104
  test('should be optional', () => {
@@ -142,15 +107,15 @@ describe(BadgeRequirement.name, () => {
142
107
  })
143
108
  })
144
109
 
145
- describe('inventionCount', () => {
110
+ describe('count', () => {
146
111
  test('should be set from the data', () => {
147
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ inventionCount: 5 }))
148
- expect(requirement.inventionCount).toEqual(5)
112
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ count: 5 }))
113
+ expect(requirement.count).toEqual(5)
149
114
  })
150
115
 
151
116
  test('should be optional', () => {
152
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('inventionCount').create())
153
- expect(requirement.inventionCount).toBeUndefined()
117
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('count').create())
118
+ expect(requirement.count).toBeUndefined()
154
119
  })
155
120
  })
156
121