coh-content-db 2.0.0-rc.5 → 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 (82) hide show
  1. package/README.md +7 -7
  2. package/dist/coh-content-db.d.ts +493 -243
  3. package/dist/coh-content-db.js +675 -353
  4. package/dist/coh-content-db.js.map +1 -1
  5. package/dist/coh-content-db.mjs +655 -345
  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 +15 -38
  11. package/src/main/api/badge-requirement-data.ts +64 -0
  12. package/src/main/api/badge-requirement-type.ts +32 -0
  13. package/src/main/api/badge-type.ts +15 -15
  14. package/src/main/api/contact-data.ts +48 -0
  15. package/src/main/api/content-bundle.ts +16 -4
  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 +20 -0
  23. package/src/main/changelog.ts +8 -3
  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 +17 -36
  27. package/src/main/db/badge-requirement.ts +81 -0
  28. package/src/main/db/badge-search-options.ts +5 -5
  29. package/src/main/db/badge.ts +73 -62
  30. package/src/main/db/bundle-metadata.ts +3 -3
  31. package/src/main/db/coh-content-database.ts +60 -23
  32. package/src/main/db/contact.ts +62 -0
  33. package/src/main/db/location.ts +30 -0
  34. package/src/main/db/mission.ts +107 -0
  35. package/src/main/db/morality-list.ts +99 -0
  36. package/src/main/db/zone.ts +28 -0
  37. package/src/main/index.ts +16 -13
  38. package/src/main/util.ts +85 -14
  39. package/src/test/api/alignment.test.ts +38 -4
  40. package/src/test/api/badge-data.fixture.ts +1 -15
  41. package/src/test/api/badge-data.test.ts +3 -3
  42. package/src/test/api/badge-requirement-data.fixture.ts +7 -0
  43. package/src/test/api/badge-requirement-type.test.ts +31 -0
  44. package/src/test/api/badge-type.test.ts +5 -5
  45. package/src/test/api/contact-data.fixture.ts +7 -0
  46. package/src/test/api/content-bundle.fixture.ts +1 -17
  47. package/src/test/api/content-bundle.test.ts +1 -1
  48. package/src/test/api/enhancement-category.test.ts +5 -5
  49. package/src/test/api/mission-data.fixture.ts +12 -0
  50. package/src/test/api/sex.test.ts +33 -1
  51. package/src/test/api/zone-data.fixture.ts +8 -0
  52. package/src/test/db/alignment-list.test.ts +200 -0
  53. package/src/test/db/alternates.test.ts +60 -56
  54. package/src/test/db/badge-index.test.ts +108 -66
  55. package/src/test/db/badge-requirement.test.ts +145 -0
  56. package/src/test/db/badge.test.ts +310 -14
  57. package/src/test/db/coh-content-database.test.ts +110 -29
  58. package/src/test/db/contact.test.ts +97 -0
  59. package/src/test/db/location.test.ts +51 -0
  60. package/src/test/db/mission.test.ts +171 -0
  61. package/src/test/db/morality-list.test.ts +457 -0
  62. package/src/test/db/zone.test.ts +36 -0
  63. package/src/test/index.test.ts +4 -2
  64. package/src/test/util.test.ts +112 -22
  65. package/src/main/api/badge-partial-data.ts +0 -66
  66. package/src/main/api/badge-partial-type.ts +0 -8
  67. package/src/main/api/game-map-data.ts +0 -26
  68. package/src/main/api/plaque-type.ts +0 -6
  69. package/src/main/api/vidiot-map-data.ts +0 -18
  70. package/src/main/api/vidiot-map-point-of-interest-data.ts +0 -30
  71. package/src/main/db/alignments.ts +0 -17
  72. package/src/main/db/badge-partial.ts +0 -83
  73. package/src/main/db/game-map.ts +0 -33
  74. package/src/main/db/vidiot-map-point-of-interest.ts +0 -39
  75. package/src/main/db/vidiot-map.ts +0 -25
  76. package/src/test/api/alignments.test.ts +0 -40
  77. package/src/test/api/badge-partial-data.fixture.ts +0 -17
  78. package/src/test/api/badge-partial-type.test.ts +0 -31
  79. package/src/test/api/game-map-data.fixture.ts +0 -10
  80. package/src/test/api/plaque-type.test.ts +0 -31
  81. package/src/test/api/vidiot-map-point-of-interest.fixture.ts +0 -10
  82. package/src/test/api/vidiot-map.fixture.ts +0 -9
@@ -1,106 +1,186 @@
1
- const ALIGNMENT = ["H", "V", "P"];
1
+ const ALIGNMENT = ["hero", "villain", "praetorian"];
2
+ const ALIGNMENT_ORDER = Object.fromEntries(ALIGNMENT.map((x, index) => [x, index]));
3
+ function compareAlignment(a, b) {
4
+ const orderA = a ? ALIGNMENT_ORDER[a] : -1;
5
+ const orderB = b ? ALIGNMENT_ORDER[b] : -1;
6
+ return orderA - orderB;
7
+ }
2
8
 
3
- const BADGE_PARTIAL_TYPE = [
4
- "PLAQUE",
5
- "BADGE",
6
- "INVENTION",
7
- "INVENTION_PLUS_ONE"
8
- // Some invention badges require you to build x of two different invention levels, 'plus one of either level'.
9
+ const BADGE_REQUIREMENT_TYPE = [
10
+ /**
11
+ * Collect a badge.
12
+ */
13
+ "badge",
14
+ /**
15
+ * Craft an invention.
16
+ */
17
+ "invention",
18
+ /**
19
+ * Some invention badges require you to build x of two different invention levels, 'plus one of either level'.
20
+ */
21
+ "invention-plus-one",
22
+ /**
23
+ * Visit a location.
24
+ */
25
+ "location",
26
+ /**
27
+ * Click on a monument.
28
+ */
29
+ "monument",
30
+ /**
31
+ * Complete a mission.
32
+ */
33
+ "mission",
34
+ /**
35
+ * Complete an arbitrary task.
36
+ */
37
+ "task"
9
38
  ];
10
39
 
11
40
  const BADGE_TYPE = [
12
- "EXPLORATION",
13
- "HISTORY",
14
- "ACCOMPLISHMENT",
15
- "ACHIEVEMENT",
16
- "ACCOLADE",
17
- "GLADIATOR",
18
- "VETERAN",
19
- "PVP",
20
- "INVENTION",
21
- "DEFEAT",
22
- "EVENT",
23
- "OUROBOROS",
24
- "CONSIGNMENT",
25
- "DAY_JOB",
26
- "AE"
41
+ "exploration",
42
+ "history",
43
+ "accomplishment",
44
+ "achievement",
45
+ "accolade",
46
+ "gladiator",
47
+ "veteran",
48
+ "pvp",
49
+ "invention",
50
+ "defeat",
51
+ "event",
52
+ "ouroboros",
53
+ "consignment",
54
+ "day-job",
55
+ "architect-entertainment"
27
56
  ];
28
57
 
29
58
  const ENHANCEMENT_CATEGORY = [
30
- "DEFENSE_DEBUFF",
31
- "TO_HIT_DEBUFF",
32
- "TAUNT",
33
- "CONFUSE",
34
- "HEALING",
35
- "DEFENSE_BUFF",
36
- "RESIST_DAMAGE",
37
- "INTANGIBILITY",
38
- "SLEEP",
39
- "SLOW",
40
- "HOLD",
41
- "STUN",
42
- "IMMOBILIZE",
43
- "FEAR",
44
- "ENDURANCE_MODIFICATION",
45
- "ENDURANCE_REDUCTION",
46
- "RECHARGE_REDUCTION",
47
- "INTERRUPT_DURATION",
48
- "ACCURACY",
49
- "TO_HIT_BUFF",
50
- "DAMAGE",
51
- "KNOCKBACK",
52
- "RUN_SPEED",
53
- "JUMP",
54
- "FLY_SPEED",
55
- "RANGE"
59
+ "defense-debuff",
60
+ "to-hit-debuff",
61
+ "taunt",
62
+ "confuse",
63
+ "healing",
64
+ "defense-buff",
65
+ "resist-damage",
66
+ "intangibility",
67
+ "sleep",
68
+ "slow",
69
+ "hold",
70
+ "stun",
71
+ "immobilize",
72
+ "fear",
73
+ "endurance-modification",
74
+ "endurance-reduction",
75
+ "recharge-reduction",
76
+ "interrupt-duration",
77
+ "accuracy",
78
+ "to-hit-buff",
79
+ "damage",
80
+ "knockback",
81
+ "run-speed",
82
+ "jump",
83
+ "fly-speed",
84
+ "range"
56
85
  ];
57
86
 
58
- const PLAQUE_TYPE = [
59
- "WALL_PLAQUE",
60
- "MONUMENT"
61
- ];
87
+ const MISSION_TYPE = ["story-arc", "mission", "task-force", "strike-force", "trial", "personal-story"];
88
+
89
+ const MORALITY = ["hero", "vigilante", "villain", "rogue", "resistance", "loyalist"];
62
90
 
63
91
  const SEX = ["M", "F"];
92
+ const SEX_ORDER = Object.fromEntries(SEX.map((x, index) => [x, index]));
93
+ function compareSex(a, b) {
94
+ const orderA = a ? SEX_ORDER[a] : -1;
95
+ const orderB = b ? SEX_ORDER[b] : -1;
96
+ return orderA - orderB;
97
+ }
64
98
 
65
- var __defProp$8 = Object.defineProperty;
66
- var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
67
- var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
68
- class Alignments {
69
- constructor(raw) {
70
- __publicField$8(this, "items");
71
- __publicField$8(this, "hero");
72
- __publicField$8(this, "villain");
73
- __publicField$8(this, "praetorian");
74
- __publicField$8(this, "primal");
75
- this.items = raw;
76
- this.hero = raw.includes("H");
77
- this.villain = raw.includes("V");
78
- this.praetorian = raw.includes("P");
79
- this.primal = !this.praetorian && (this.hero || this.villain);
99
+ var __defProp$a = Object.defineProperty;
100
+ var __typeError$6 = (msg) => {
101
+ throw TypeError(msg);
102
+ };
103
+ var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
104
+ var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
105
+ var __accessCheck$6 = (obj, member, msg) => member.has(obj) || __typeError$6("Cannot " + msg);
106
+ var __privateGet$6 = (obj, member, getter) => (__accessCheck$6(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
107
+ var __privateAdd$6 = (obj, member, value) => member.has(obj) ? __typeError$6("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
108
+ var __privateSet$5 = (obj, member, value, setter) => (__accessCheck$6(obj, member, "write to private field"), member.set(obj, value), value);
109
+ var _items$1;
110
+ class AlignmentList {
111
+ constructor(items) {
112
+ __privateAdd$6(this, _items$1);
113
+ __publicField$a(this, "hero");
114
+ __publicField$a(this, "villain");
115
+ __publicField$a(this, "praetorian");
116
+ __publicField$a(this, "primal");
117
+ __publicField$a(this, "all");
118
+ const set = new Set(items ?? [...ALIGNMENT]);
119
+ this.hero = set.has("hero") || set.has("primal") || set.has("all");
120
+ this.villain = set.has("villain") || set.has("primal") || set.has("all");
121
+ this.praetorian = set.has("praetorian") || set.has("all");
122
+ this.primal = this.hero && this.villain;
123
+ this.all = this.hero && this.villain && this.praetorian;
124
+ __privateSet$5(this, _items$1, /* @__PURE__ */ new Set());
125
+ if (this.hero) __privateGet$6(this, _items$1).add("hero");
126
+ if (this.villain) __privateGet$6(this, _items$1).add("villain");
127
+ if (this.praetorian) __privateGet$6(this, _items$1).add("praetorian");
128
+ }
129
+ get items() {
130
+ return [...__privateGet$6(this, _items$1)];
131
+ }
132
+ has(alignment) {
133
+ switch (alignment) {
134
+ case "hero": {
135
+ return this.hero;
136
+ }
137
+ case "villain": {
138
+ return this.villain;
139
+ }
140
+ case "praetorian": {
141
+ return this.praetorian;
142
+ }
143
+ case "primal": {
144
+ return this.primal;
145
+ }
146
+ case "all": {
147
+ return this.all;
148
+ }
149
+ default: {
150
+ return false;
151
+ }
152
+ }
80
153
  }
81
154
  }
155
+ _items$1 = new WeakMap();
82
156
 
83
- var __typeError$4 = (msg) => {
157
+ var __typeError$5 = (msg) => {
84
158
  throw TypeError(msg);
85
159
  };
86
- var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg);
87
- var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
88
- var __privateAdd$4 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
89
- var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
90
- var __privateMethod$2 = (obj, member, method) => (__accessCheck$4(obj, member, "access private method"), method);
91
- var _sortedValues, _Alternates_instances, compareAlternates_fn, compareAlignment_fn, compareSex_fn;
92
- const ALIGNMENT_SORT = { H: 2, V: 1, P: 0 };
93
- const SEX_SORT = { M: 1, F: 0 };
160
+ var __accessCheck$5 = (obj, member, msg) => member.has(obj) || __typeError$5("Cannot " + msg);
161
+ var __privateGet$5 = (obj, member, getter) => (__accessCheck$5(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
162
+ var __privateAdd$5 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
163
+ var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), member.set(obj, value), value);
164
+ var __privateMethod$2 = (obj, member, method) => (__accessCheck$5(obj, member, "access private method"), method);
165
+ var _sortedValues, _Alternates_instances, compareAlternates_fn;
94
166
  class Alternates {
95
- constructor(values) {
96
- __privateAdd$4(this, _Alternates_instances);
97
- __privateAdd$4(this, _sortedValues, []);
98
- __privateSet$3(this, _sortedValues, values.sort());
99
- __privateGet$4(this, _sortedValues).sort((a, b) => __privateMethod$2(this, _Alternates_instances, compareAlternates_fn).call(this, a, b));
167
+ /**
168
+ * Create an alternate set from either a list of categorized values, or a single value when there are no alternates.
169
+ * @param value List of alternates, or a single value.
170
+ */
171
+ constructor(value) {
172
+ __privateAdd$5(this, _Alternates_instances);
173
+ __privateAdd$5(this, _sortedValues, []);
174
+ if (Array.isArray(value)) {
175
+ __privateSet$4(this, _sortedValues, value.sort());
176
+ __privateGet$5(this, _sortedValues).sort((a, b) => __privateMethod$2(this, _Alternates_instances, compareAlternates_fn).call(this, a, b));
177
+ } else {
178
+ __privateSet$4(this, _sortedValues, [{ value }]);
179
+ }
100
180
  }
101
181
  getValue(alignment, sex) {
102
- for (let index = __privateGet$4(this, _sortedValues).length; index--; ) {
103
- const entry = __privateGet$4(this, _sortedValues)[index];
182
+ for (let index = __privateGet$5(this, _sortedValues).length; index--; ) {
183
+ const entry = __privateGet$5(this, _sortedValues)[index];
104
184
  if ((entry.alignment === void 0 || entry.alignment === alignment) && (entry.sex === void 0 || entry.sex === sex)) return entry.value;
105
185
  }
106
186
  return this.default?.value;
@@ -109,13 +189,13 @@ class Alternates {
109
189
  * Get the default value for this list of alternates, the value with the highest priority and lowest specificity.
110
190
  */
111
191
  get default() {
112
- return __privateGet$4(this, _sortedValues)[0];
192
+ return __privateGet$5(this, _sortedValues)[0];
113
193
  }
114
194
  /**
115
195
  * Get the list of alternates sorted in canonical order (alignment then sex, low to high specificity).
116
196
  */
117
197
  get canonical() {
118
- return __privateGet$4(this, _sortedValues);
198
+ return __privateGet$5(this, _sortedValues);
119
199
  }
120
200
  /**
121
201
  * Create a joined string from the alternate values in canonical order.
@@ -131,48 +211,32 @@ compareAlternates_fn = function(a, b) {
131
211
  const aSpecificity = (a.alignment ? 2 : 0) + (a.sex ? 1 : 0);
132
212
  const bSpecificity = (b.alignment ? 2 : 0) + (b.sex ? 1 : 0);
133
213
  if (aSpecificity !== bSpecificity) return aSpecificity - bSpecificity;
134
- const alignmentComparison = __privateMethod$2(this, _Alternates_instances, compareAlignment_fn).call(this, a.alignment, b.alignment);
214
+ const alignmentComparison = compareAlignment(a.alignment, b.alignment);
135
215
  if (alignmentComparison !== 0) return alignmentComparison;
136
- const sexComparison = __privateMethod$2(this, _Alternates_instances, compareSex_fn).call(this, a.sex, b.sex);
216
+ const sexComparison = compareSex(a.sex, b.sex);
137
217
  if (sexComparison !== 0) return sexComparison;
138
218
  return String(a.value).localeCompare(String(b.value));
139
219
  };
140
- compareAlignment_fn = function(a, b) {
141
- if (a === b) return 0;
142
- if (a === void 0 && b !== void 0) return -1;
143
- if (b === void 0 && a !== void 0) return 1;
144
- const aSort = a === void 0 ? -1 : ALIGNMENT_SORT[a] ?? -1;
145
- const bSort = b === void 0 ? -1 : ALIGNMENT_SORT[b] ?? -1;
146
- return bSort - aSort;
147
- };
148
- compareSex_fn = function(a, b) {
149
- if (a === b) return 0;
150
- if (a === void 0 && b !== void 0) return -1;
151
- if (b === void 0 && a !== void 0) return 1;
152
- const aSort = SEX_SORT[a ?? -1] ?? -1;
153
- const bSort = SEX_SORT[b ?? -1] ?? -1;
154
- return bSort - aSort;
155
- };
156
220
 
157
- var __typeError$3 = (msg) => {
221
+ var __typeError$4 = (msg) => {
158
222
  throw TypeError(msg);
159
223
  };
160
- var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
161
- var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
162
- var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$3("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
163
- var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
164
- var __privateMethod$1 = (obj, member, method) => (__accessCheck$3(obj, member, "access private method"), method);
224
+ var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg);
225
+ var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
226
+ var __privateAdd$4 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
227
+ var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
228
+ var __privateMethod$1 = (obj, member, method) => (__accessCheck$4(obj, member, "access private method"), method);
165
229
  var _value, _Key_instances, validateKey_fn;
166
230
  const INVALID_KEY_PATTERN = /[^a-z0-9-]/;
167
231
  class Key {
168
232
  constructor(value) {
169
- __privateAdd$3(this, _Key_instances);
170
- __privateAdd$3(this, _value);
233
+ __privateAdd$4(this, _Key_instances);
234
+ __privateAdd$4(this, _value);
171
235
  __privateMethod$1(this, _Key_instances, validateKey_fn).call(this, value);
172
- __privateSet$2(this, _value, value);
236
+ __privateSet$3(this, _value, value);
173
237
  }
174
238
  get value() {
175
- return __privateGet$3(this, _value);
239
+ return __privateGet$4(this, _value);
176
240
  }
177
241
  }
178
242
  _value = new WeakMap();
@@ -181,198 +245,352 @@ validateKey_fn = function(key) {
181
245
  if (INVALID_KEY_PATTERN.test(key)) throw new Error(`Invalid key: [${key}]; Keys can only contain lowercase characters, numbers and dashes.`);
182
246
  };
183
247
 
184
- var __defProp$7 = Object.defineProperty;
185
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
186
- var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
248
+ var __defProp$9 = Object.defineProperty;
249
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
250
+ var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
187
251
  class Archetype {
188
252
  constructor(data) {
189
- __publicField$7(this, "key");
190
- __publicField$7(this, "name");
191
- __publicField$7(this, "description");
253
+ __publicField$9(this, "key");
254
+ __publicField$9(this, "name");
255
+ __publicField$9(this, "description");
192
256
  this.key = new Key(data.key).value;
193
257
  this.name = data.name;
194
258
  this.description = data.description;
195
259
  }
196
260
  }
197
261
 
198
- var __defProp$6 = Object.defineProperty;
199
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
200
- var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
201
- class BadgePartial {
262
+ function badgeUri(target) {
263
+ const key = typeof target === "string" ? target : target.key;
264
+ return `badge://${key}`;
265
+ }
266
+ function badgeLink(target) {
267
+ const key = typeof target === "string" ? target : target.key;
268
+ return `[${key}](${badgeUri(target)})`;
269
+ }
270
+ function contactUri(target) {
271
+ const key = typeof target === "string" ? target : target.key;
272
+ return `contact://${key}`;
273
+ }
274
+ function contactLink(target) {
275
+ const key = typeof target === "string" ? target : target.key;
276
+ return `[${key}](${contactUri(target)})`;
277
+ }
278
+ function missionUri(target) {
279
+ const key = typeof target === "string" ? target : target.key;
280
+ return `mission://${key}`;
281
+ }
282
+ function missionLink(target) {
283
+ const key = typeof target === "string" ? target : target.key;
284
+ return `[${key}](${missionUri(target)})`;
285
+ }
286
+ function zoneUri(target) {
287
+ const key = typeof target === "string" ? target : target.key;
288
+ return `zone://${key}`;
289
+ }
290
+ function zoneLink(target) {
291
+ const key = typeof target === "string" ? target : target.key;
292
+ return `[${key}](${zoneUri(target)})`;
293
+ }
294
+ function coalesceToArray(value) {
295
+ if (!value) return void 0;
296
+ return Array.isArray(value) ? value : [value];
297
+ }
298
+
299
+ var __defProp$8 = Object.defineProperty;
300
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
301
+ var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
302
+ class BadgeRequirement {
202
303
  constructor(data) {
203
304
  /**
204
- * Key.
205
- */
206
- __publicField$6(this, "key");
207
- /**
208
- * Type of partial.
305
+ * Unique key used to reference this badge requirement.
306
+ *
307
+ * Keys must be unique and can only contain lowercase letters, numbers and hyphens (`-`).
209
308
  */
210
- __publicField$6(this, "type");
309
+ __publicField$8(this, "key");
211
310
  /**
212
- * Map the partial is located on.
311
+ * The requirement type.
213
312
  */
214
- __publicField$6(this, "mapKey");
313
+ __publicField$8(this, "type");
215
314
  /**
216
- * /loc coordinates.
315
+ * If the requirement involves a location, where it is.
217
316
  */
218
- __publicField$6(this, "loc");
317
+ __publicField$8(this, "location");
219
318
  /**
220
- * Is it a wall plaque or a physical monument?
319
+ * If the requirement involves a badge, the badge key.
221
320
  */
222
- __publicField$6(this, "plaqueType");
321
+ __publicField$8(this, "badgeKey");
223
322
  /**
224
- * Plaque inscription.
323
+ * If the requirement involves a mission, the mission key.
225
324
  */
226
- __publicField$6(this, "plaqueInscription");
325
+ __publicField$8(this, "missionKey");
227
326
  /**
228
- * The number or letter the partial appears as on Vidiot Maps.
327
+ * If the requirement involves a monument, the text that is displayed thereon.
229
328
  */
230
- __publicField$6(this, "vidiotMapKey");
329
+ __publicField$8(this, "monumentText");
231
330
  /**
232
- * The badge required for this partial.
331
+ * If the requirement involves crafting an invention, the Level of the invention required.
233
332
  */
234
- __publicField$6(this, "badgeKey");
333
+ __publicField$8(this, "inventionLevel");
235
334
  /**
236
- * Level of the invention required.
335
+ * If the requirement involves crafting an invention, the types of enhancements that will qualify.
237
336
  */
238
- __publicField$6(this, "inventionLevel");
337
+ __publicField$8(this, "inventionTypes");
239
338
  /**
240
- * The types of enhancements required to be crafted.
339
+ * Number of times the task needs to be repeated.
241
340
  */
242
- __publicField$6(this, "inventionTypes");
341
+ __publicField$8(this, "count");
243
342
  /**
244
- * Number of invention crafts required.
343
+ * Additional information about the requirement.
245
344
  */
246
- __publicField$6(this, "inventionCount");
345
+ __publicField$8(this, "notes");
247
346
  /**
248
- * Any additional notes.
347
+ * List of external links. Wiki, forums, etc.
249
348
  */
250
- __publicField$6(this, "notes");
349
+ __publicField$8(this, "links");
251
350
  this.key = new Key(data.key).value;
252
351
  this.type = data.type;
253
- this.mapKey = data.mapKey;
254
- this.loc = data.loc;
255
- this.plaqueType = data.plaqueType;
256
- this.plaqueInscription = data.plaqueInscription;
257
- this.vidiotMapKey = data.vidiotMapKey;
352
+ this.location = coalesceToArray(data.location);
258
353
  this.badgeKey = data.badgeKey;
354
+ this.missionKey = data.missionKey;
355
+ this.monumentText = data.monumentText;
259
356
  this.inventionLevel = data.inventionLevel;
260
357
  this.inventionTypes = data.inventionTypes;
261
- this.inventionCount = data.inventionCount;
358
+ this.count = data.count;
262
359
  this.notes = data.notes;
360
+ this.links = data.links ?? [];
263
361
  }
264
362
  }
265
363
 
266
- var __defProp$5 = Object.defineProperty;
364
+ var __defProp$7 = Object.defineProperty;
365
+ var __typeError$3 = (msg) => {
366
+ throw TypeError(msg);
367
+ };
368
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
369
+ var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
370
+ var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
371
+ var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
372
+ var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$3("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
373
+ var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
374
+ var _items;
375
+ class MoralityList {
376
+ constructor(items) {
377
+ __privateAdd$3(this, _items);
378
+ __publicField$7(this, "hero");
379
+ __publicField$7(this, "vigilante");
380
+ __publicField$7(this, "villain");
381
+ __publicField$7(this, "rogue");
382
+ __publicField$7(this, "resistance");
383
+ __publicField$7(this, "loyalist");
384
+ __publicField$7(this, "primal");
385
+ __publicField$7(this, "praetorian");
386
+ __publicField$7(this, "heroic");
387
+ __publicField$7(this, "villainous");
388
+ __publicField$7(this, "paragonCityAccess");
389
+ __publicField$7(this, "rogueIslesAccess");
390
+ __publicField$7(this, "all");
391
+ const set = new Set(items ?? [...MORALITY]);
392
+ this.hero = set.has("hero") || set.has("primal") || set.has("heroic") || set.has("paragon-city-access") || set.has("all");
393
+ this.vigilante = set.has("vigilante") || set.has("primal") || set.has("heroic") || set.has("paragon-city-access") || set.has("rogue-isles-access") || set.has("all");
394
+ this.villain = set.has("villain") || set.has("primal") || set.has("villainous") || set.has("rogue-isles-access") || set.has("all");
395
+ this.rogue = set.has("rogue") || set.has("primal") || set.has("villainous") || set.has("paragon-city-access") || set.has("rogue-isles-access") || set.has("all");
396
+ this.resistance = set.has("resistance") || set.has("praetorian") || set.has("all");
397
+ this.loyalist = set.has("loyalist") || set.has("praetorian") || set.has("all");
398
+ this.primal = this.hero && this.vigilante && this.villain && this.rogue;
399
+ this.praetorian = this.loyalist && this.resistance;
400
+ this.heroic = this.hero && this.vigilante;
401
+ this.villainous = this.villain && this.rogue;
402
+ this.paragonCityAccess = this.heroic && this.rogue;
403
+ this.rogueIslesAccess = this.villainous && this.vigilante;
404
+ this.all = this.primal && this.praetorian;
405
+ __privateSet$2(this, _items, /* @__PURE__ */ new Set());
406
+ if (this.hero) __privateGet$3(this, _items).add("hero");
407
+ if (this.vigilante) __privateGet$3(this, _items).add("vigilante");
408
+ if (this.villain) __privateGet$3(this, _items).add("villain");
409
+ if (this.rogue) __privateGet$3(this, _items).add("rogue");
410
+ if (this.resistance) __privateGet$3(this, _items).add("resistance");
411
+ if (this.loyalist) __privateGet$3(this, _items).add("loyalist");
412
+ }
413
+ get items() {
414
+ return [...__privateGet$3(this, _items)];
415
+ }
416
+ has(morality) {
417
+ switch (morality) {
418
+ case "hero": {
419
+ return this.hero;
420
+ }
421
+ case "vigilante": {
422
+ return this.vigilante;
423
+ }
424
+ case "villain": {
425
+ return this.villain;
426
+ }
427
+ case "rogue": {
428
+ return this.rogue;
429
+ }
430
+ case "resistance": {
431
+ return this.resistance;
432
+ }
433
+ case "loyalist": {
434
+ return this.loyalist;
435
+ }
436
+ case "primal": {
437
+ return this.primal;
438
+ }
439
+ case "praetorian": {
440
+ return this.praetorian;
441
+ }
442
+ case "heroic": {
443
+ return this.hero;
444
+ }
445
+ case "paragon-city-access": {
446
+ return this.paragonCityAccess;
447
+ }
448
+ case "rogue-isles-access": {
449
+ return this.rogueIslesAccess;
450
+ }
451
+ case "villainous": {
452
+ return this.villainous;
453
+ }
454
+ case "all": {
455
+ return this.all;
456
+ }
457
+ default: {
458
+ return false;
459
+ }
460
+ }
461
+ }
462
+ }
463
+ _items = new WeakMap();
464
+
465
+ var __defProp$6 = Object.defineProperty;
267
466
  var __typeError$2 = (msg) => {
268
467
  throw TypeError(msg);
269
468
  };
270
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
271
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
469
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
470
+ var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
272
471
  var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
273
472
  var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
274
473
  var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
275
- var _partialsIndex;
474
+ var _requirementsIndex, _zoneKeys;
276
475
  class Badge {
277
- constructor(data) {
278
- __privateAdd$2(this, _partialsIndex, {});
476
+ constructor(badgeData) {
477
+ __privateAdd$2(this, _requirementsIndex, {});
478
+ __privateAdd$2(this, _zoneKeys, /* @__PURE__ */ new Set());
279
479
  /**
280
480
  * The database key for this badge.
281
481
  */
282
- __publicField$5(this, "key");
482
+ __publicField$6(this, "key");
283
483
  /**
284
484
  * The type of badge.
285
485
  */
286
- __publicField$5(this, "type");
486
+ __publicField$6(this, "type");
287
487
  /**
288
488
  * The name of this badge.
289
489
  *
290
490
  * May vary by character sex or alignment.
291
491
  */
292
- __publicField$5(this, "name");
492
+ __publicField$6(this, "name");
293
493
  /**
294
- * The character alignments that this badge is available to.
494
+ * The character moralities that this badge is available to.
295
495
  */
296
- __publicField$5(this, "alignment");
496
+ __publicField$6(this, "morality");
297
497
  /**
298
498
  * The badge text as it appears in-game. May vary by character sex or alignment.
299
499
  */
300
- __publicField$5(this, "badgeText");
500
+ __publicField$6(this, "badgeText");
301
501
  /**
302
- * Description of how to acquire the badge.
502
+ * Short description of how to acquire the badge. Detailed instructions will be in the notes field.
303
503
  */
304
- __publicField$5(this, "acquisition");
504
+ __publicField$6(this, "acquisition");
305
505
  /**
306
506
  * Absolute URL to this badge's icon.
307
507
  *
308
508
  * May vary by character sex or alignment.
309
509
  */
310
- __publicField$5(this, "icon");
510
+ __publicField$6(this, "icon");
311
511
  /**
312
512
  * Freeform notes or tips about the badge.
313
513
  */
314
- __publicField$5(this, "notes");
315
- /**
316
- * List of external links for this Badge. Wiki, forums, etc.
317
- */
318
- __publicField$5(this, "links");
319
- /**
320
- * For exploration badges, the key of the {@link GameMap} that this badge is found on.
321
- */
322
- __publicField$5(this, "mapKey");
323
- /**
324
- * For exploration badges, the `/loc` coordinates of the badge on the in-game map.
325
- */
326
- __publicField$5(this, "loc");
514
+ __publicField$6(this, "notes");
327
515
  /**
328
- * For badges that appear on a Vidiot Map, the number or letter the badge appears as.
516
+ * List of external links. Wiki, forums, etc.
329
517
  */
330
- __publicField$5(this, "vidiotMapKey");
518
+ __publicField$6(this, "links");
331
519
  /**
332
- * ID used with the in-game `/settitle` command to apply the badge.
520
+ * The id used with the in-game `/settitle` command to apply the badge.
521
+ * The first value is the id for primal characters and the (optional) second number is the id for praetorian characters.
333
522
  */
334
- __publicField$5(this, "setTitle");
523
+ __publicField$6(this, "setTitleId");
335
524
  /**
336
525
  * A description of the effect the badge will have, such as a buff or granting a temporary power.
337
526
  */
338
- __publicField$5(this, "effect");
527
+ __publicField$6(this, "effect");
339
528
  /**
340
- * A list of requirements for badges that have partial fulfilment steps, such as visiting plaques for history badges, or collecting other badges for meta-badges like accolades.
529
+ * Represents the requirements for badges with multiple fulfillment steps, such as visiting monuments for history badges, completing missions, or collecting other badges.
341
530
  */
342
- __publicField$5(this, "partials");
531
+ __publicField$6(this, "requirements");
343
532
  /**
344
533
  * Some badges are not included in the badge total count... such as Flames of Prometheus, which can be removed by redeeming it for a Notice of the Well.
345
534
  */
346
- __publicField$5(this, "ignoreInTotals");
347
- this.key = new Key(data.key).value;
348
- this.type = data.type;
349
- this.name = new Alternates(data.name);
350
- this.alignment = new Alignments(data.alignment);
351
- this.badgeText = new Alternates(data.badgeText ?? []);
352
- this.acquisition = data.acquisition;
353
- this.icon = new Alternates(data.icon ?? []);
354
- this.notes = data.notes;
355
- this.links = data.links;
356
- this.mapKey = data.mapKey;
357
- this.loc = data.loc;
358
- this.effect = data.effect;
359
- this.vidiotMapKey = data.vidiotMapKey;
360
- this.setTitle = data.setTitle;
361
- this.ignoreInTotals = data.ignoreInTotals ?? false;
362
- this.partials = data.partials?.map((data2) => {
363
- if (__privateGet$2(this, _partialsIndex)[data2.key] !== void 0) throw new Error(`Duplicate badge partial key [${data2.key}]`);
364
- const badge = new BadgePartial(data2);
365
- __privateGet$2(this, _partialsIndex)[badge.key] = badge;
366
- return badge;
535
+ __publicField$6(this, "ignoreInTotals");
536
+ this.key = new Key(badgeData.key).value;
537
+ this.type = badgeData.type;
538
+ this.name = new Alternates(badgeData.name);
539
+ this.morality = new MoralityList(coalesceToArray(badgeData.morality));
540
+ this.badgeText = new Alternates(badgeData.badgeText ?? []);
541
+ this.acquisition = badgeData.acquisition;
542
+ this.icon = new Alternates(badgeData.icon ?? []);
543
+ this.notes = badgeData.notes;
544
+ this.links = badgeData.links ?? [];
545
+ this.effect = badgeData.effect;
546
+ this.setTitleId = badgeData.setTitleId;
547
+ this.ignoreInTotals = badgeData.ignoreInTotals ?? false;
548
+ this.requirements = badgeData.requirements?.map((requirementData) => {
549
+ if (__privateGet$2(this, _requirementsIndex)[requirementData.key]) throw new Error(`Duplicate badge requirement key [${badgeData.key}:${requirementData.key}]`);
550
+ const requirement = new BadgeRequirement(requirementData);
551
+ __privateGet$2(this, _requirementsIndex)[requirement.key] = requirement;
552
+ if (requirement.location) for (const location of requirement.location) {
553
+ if (location.zoneKey) __privateGet$2(this, _zoneKeys).add(location.zoneKey);
554
+ }
555
+ return requirement;
367
556
  });
368
557
  }
369
- getPartial(key) {
370
- const result = __privateGet$2(this, _partialsIndex)[key];
371
- if (result === void 0) throw new Error(`Unknown badge partial key [${key}]`);
558
+ getRequirement(key) {
559
+ const result = __privateGet$2(this, _requirementsIndex)[key];
560
+ if (result === void 0) throw new Error(`Unknown badge requirement key [${key}]`);
372
561
  return result;
373
562
  }
563
+ /**
564
+ * Return a list of all the zone keys referenced by this badge.
565
+ */
566
+ get zoneKeys() {
567
+ return [...__privateGet$2(this, _zoneKeys)];
568
+ }
569
+ /**
570
+ * The zone key if this badge relates to a single zone.
571
+ */
572
+ get zoneKey() {
573
+ return __privateGet$2(this, _zoneKeys).size === 1 ? __privateGet$2(this, _zoneKeys).values().next().value : void 0;
574
+ }
575
+ }
576
+ _requirementsIndex = new WeakMap();
577
+ _zoneKeys = new WeakMap();
578
+ function compareByDefaultName(a, b) {
579
+ const aName = a?.name.default?.value;
580
+ const bName = b?.name.default?.value;
581
+ if (!aName && !bName) return 0;
582
+ if (!aName) return 1;
583
+ if (!bName) return -1;
584
+ return aName.localeCompare(bName);
585
+ }
586
+ function compareByZoneKey(a, b) {
587
+ const aZone = a?.zoneKey;
588
+ const bZone = b?.zoneKey;
589
+ if (!aZone && !bZone) return 0;
590
+ if (!aZone) return 1;
591
+ if (!bZone) return -1;
592
+ return aZone.localeCompare(bZone);
374
593
  }
375
- _partialsIndex = new WeakMap();
376
594
 
377
595
  var __typeError$1 = (msg) => {
378
596
  throw TypeError(msg);
@@ -382,16 +600,12 @@ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "rea
382
600
  var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
383
601
  var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
384
602
  var __privateMethod = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
385
- var _badges, _badgeIndex$1, _mapOrder, _BadgeIndex_instances, satisfiesQueryPredicate_fn, satisfiesFilterPredicate_fn, sort_fn;
603
+ var _badges, _badgeIndex$1, _BadgeIndex_instances, satisfiesQueryPredicate_fn, satisfiesFilterPredicate_fn, sort_fn;
386
604
  class BadgeIndex {
387
- constructor(badges, maps) {
605
+ constructor(badges) {
388
606
  __privateAdd$1(this, _BadgeIndex_instances);
389
607
  __privateAdd$1(this, _badges, []);
390
608
  __privateAdd$1(this, _badgeIndex$1, {});
391
- __privateAdd$1(this, _mapOrder, {});
392
- __privateSet$1(this, _mapOrder, Object.fromEntries(
393
- maps?.sort((a, b) => a.name.localeCompare(b.name))?.map((x, index) => [x.key, index]) ?? []
394
- ));
395
609
  __privateSet$1(this, _badges, badges);
396
610
  for (const badge of badges) {
397
611
  if (__privateGet$1(this, _badgeIndex$1)[badge.key] !== void 0) throw new Error(`Duplicate badge key [${badge.key}]`);
@@ -399,74 +613,67 @@ class BadgeIndex {
399
613
  }
400
614
  }
401
615
  getBadge(key) {
402
- const result = __privateGet$1(this, _badgeIndex$1)[key];
403
- if (result === void 0) throw new Error(`Unknown badge key [${key}]`);
404
- return result;
616
+ if (!key) return void 0;
617
+ return __privateGet$1(this, _badgeIndex$1)[key];
405
618
  }
406
619
  searchBadges(options) {
407
620
  const filtered = options?.query || options?.filter ? __privateGet$1(this, _badges).filter((badge) => __privateMethod(this, _BadgeIndex_instances, satisfiesQueryPredicate_fn).call(this, badge, options?.query) && __privateMethod(this, _BadgeIndex_instances, satisfiesFilterPredicate_fn).call(this, badge, options?.filter)) : __privateGet$1(this, _badges);
408
- const paged = options?.pageSize ? filtered.slice(((options?.page ?? 1) - 1) * options.pageSize, (options?.page ?? 1) * options?.pageSize) : filtered;
621
+ const totalPages = options?.pageSize ? Math.ceil(filtered.length / options?.pageSize) : 1;
622
+ const page = Math.max(1, Math.min(totalPages, options?.page ?? 1));
623
+ const paged = options?.pageSize ? filtered.slice((page - 1) * options.pageSize, page * options?.pageSize) : filtered;
409
624
  const sorted = __privateMethod(this, _BadgeIndex_instances, sort_fn).call(this, paged, options?.sort);
410
625
  return {
411
626
  items: sorted,
412
- page: options?.page ?? 1,
627
+ page,
413
628
  pageSize: options?.pageSize,
414
629
  totalItems: filtered.length,
415
- totalPages: options?.pageSize ? Math.ceil(filtered.length / options?.pageSize) : 1
630
+ totalPages
416
631
  };
417
632
  }
418
633
  }
419
634
  _badges = new WeakMap();
420
635
  _badgeIndex$1 = new WeakMap();
421
- _mapOrder = new WeakMap();
422
636
  _BadgeIndex_instances = new WeakSet();
423
637
  satisfiesQueryPredicate_fn = function(badge, query) {
424
638
  const queryString = query?.str?.toLowerCase() ?? "";
425
- return !!((query?.on?.name ?? true) && badge.name.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || query?.on?.badgeText && badge.badgeText.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || query?.on?.acquisition && badge.acquisition?.toLowerCase().includes(queryString) || query?.on?.effect && badge.effect?.toLowerCase().includes(queryString) || query?.on?.notes && badge.notes?.toLowerCase().includes(queryString) || query?.on?.setTitle && (badge.setTitle?.id?.toString().includes(queryString) || badge.setTitle?.praetorianId?.toString().includes(queryString)));
639
+ return !!((query?.on?.name ?? true) && badge.name.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || query?.on?.badgeText && badge.badgeText.canonical.some((x) => x.value.toLowerCase().includes(queryString)) || query?.on?.acquisition && badge.acquisition?.toLowerCase().includes(queryString) || query?.on?.effect && badge.effect?.toLowerCase().includes(queryString) || query?.on?.notes && badge.notes?.toLowerCase().includes(queryString) || query?.on?.setTitle && badge.setTitleId?.some((x) => x?.toString().includes(queryString)));
426
640
  };
427
641
  satisfiesFilterPredicate_fn = function(badge, filter) {
428
- return (!filter?.type || badge.type === filter.type) && (!filter?.mapKey || badge.mapKey === filter.mapKey) && (!filter?.alignment || badge.alignment.items.includes(filter.alignment));
642
+ return (!filter?.type || badge.type === filter.type) && (!filter?.zoneKey || badge.zoneKey === filter.zoneKey) && (!filter?.morality || badge.morality.has(filter.morality));
429
643
  };
430
644
  sort_fn = function(badges, sort) {
431
645
  if (!sort) return badges;
432
- const ascending = sort.dir !== "DESC";
433
- if (!sort.by || sort.by === "CANONICAL") return sort.dir === "DESC" ? badges.reverse() : badges;
434
- if (sort.by === "BADGE_NAME") return ascending ? badges.sort((a, b) => a.name.default?.value.localeCompare(b.name.default?.value ?? "") ?? 0) : badges.sort((a, b) => b.name.default?.value.localeCompare(a.name.default?.value ?? "") ?? 0);
435
- return badges.sort((a, b) => {
436
- const aIndex = __privateGet$1(this, _mapOrder)[a.mapKey ?? ""];
437
- const bIndex = __privateGet$1(this, _mapOrder)[b.mapKey ?? ""];
438
- if (aIndex === bIndex) return 0;
439
- if (aIndex === void 0) return ascending ? 1 : -1;
440
- if (bIndex === void 0) return ascending ? -1 : 1;
441
- return ascending ? aIndex - bIndex : bIndex - aIndex;
442
- });
646
+ const ascending = sort.dir !== "desc";
647
+ if (sort.by === "badge-name") return badges.sort((a, b) => ascending ? compareByDefaultName(a, b) : compareByDefaultName(b, a));
648
+ if (sort.by === "zone-key") return badges.sort((a, b) => ascending ? compareByZoneKey(a, b) : compareByZoneKey(b, a));
649
+ return sort.dir === "desc" ? badges.reverse() : badges;
443
650
  };
444
651
 
445
- var __defProp$4 = Object.defineProperty;
446
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
447
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
652
+ var __defProp$5 = Object.defineProperty;
653
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
654
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
448
655
  class BundleMetadata {
449
656
  constructor(bundle) {
450
657
  /**
451
- * Name of the server group.
658
+ * Name of the content bundle.
452
659
  */
453
- __publicField$4(this, "name");
660
+ __publicField$5(this, "name");
454
661
  /**
455
- * Description of the server group.
662
+ * Description of the fork.
456
663
  */
457
- __publicField$4(this, "description");
664
+ __publicField$5(this, "description");
458
665
  /**
459
666
  * Repository where the db content package is maintained.
460
667
  */
461
- __publicField$4(this, "repository");
668
+ __publicField$5(this, "repository");
462
669
  /**
463
- * List of external links for this Server Group. Wiki, forums, etc.
670
+ * List of external links. Wiki, forums, etc.
464
671
  */
465
- __publicField$4(this, "links");
672
+ __publicField$5(this, "links");
466
673
  /**
467
674
  * Change log for this data package.
468
675
  */
469
- __publicField$4(this, "changelog");
676
+ __publicField$5(this, "changelog");
470
677
  this.name = bundle.name;
471
678
  this.description = bundle.description;
472
679
  this.repository = bundle.repository;
@@ -475,103 +682,159 @@ class BundleMetadata {
475
682
  }
476
683
  }
477
684
 
685
+ var __defProp$4 = Object.defineProperty;
686
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
687
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
688
+ class Zone {
689
+ constructor(data) {
690
+ /**
691
+ * Unique key used to reference this zone.
692
+ *
693
+ * Keys must be unique and can only contain lowercase letters, numbers and hyphens (`-`).
694
+ */
695
+ __publicField$4(this, "key");
696
+ /**
697
+ * The name of the zone as it appears in-game.
698
+ */
699
+ __publicField$4(this, "name");
700
+ /**
701
+ * List of external links. Wiki, forums, etc.
702
+ */
703
+ __publicField$4(this, "links");
704
+ this.key = new Key(data.key).value;
705
+ this.name = data.name;
706
+ this.links = data.links ?? [];
707
+ }
708
+ }
709
+
478
710
  var __defProp$3 = Object.defineProperty;
479
711
  var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
480
712
  var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
481
- class VidiotMapPointOfInterest {
713
+ class Contact {
482
714
  constructor(data) {
483
715
  /**
484
- * The pixel-space position of the PoI on the map graphic.
716
+ * Unique key used to reference this contact.
485
717
  *
486
- * Screen-space, pixels from top-left `[0, 0]`.
718
+ * Keys must be unique and can only contain lowercase letters, numbers and hyphens (`-`).
487
719
  */
488
- __publicField$3(this, "pos");
720
+ __publicField$3(this, "key");
489
721
  /**
490
- * Freeform notes about the PoI.
722
+ * The name of this contact.
491
723
  */
492
- __publicField$3(this, "notes");
724
+ __publicField$3(this, "name");
493
725
  /**
494
- * If the POI is a zone transfer, the map it transfers to.
726
+ * The contact's title.
495
727
  */
496
- __publicField$3(this, "mapKey");
728
+ __publicField$3(this, "title");
497
729
  /**
498
- * If the POI is a badge, the badge.
730
+ * The character moralities that this contact will interact with.
499
731
  */
500
- __publicField$3(this, "badgeKey");
732
+ __publicField$3(this, "morality");
501
733
  /**
502
- * If the POI is a partial for a badge, the partial key.
734
+ * The location of this contact.
503
735
  */
504
- __publicField$3(this, "badgePartialKey");
505
- this.pos = data.pos;
736
+ __publicField$3(this, "location");
737
+ /**
738
+ * The level range this contact will offer missions for.
739
+ */
740
+ __publicField$3(this, "levelRange");
741
+ /**
742
+ * Freeform notes or tips about the contact.
743
+ */
744
+ __publicField$3(this, "notes");
745
+ /**
746
+ * List of external links. Wiki, forums, etc.
747
+ */
748
+ __publicField$3(this, "links");
749
+ this.key = new Key(data.key).value;
750
+ this.name = data.name;
751
+ this.title = data.title;
752
+ this.morality = new MoralityList(coalesceToArray(data.morality));
753
+ this.location = data.location;
754
+ this.levelRange = data.levelRange;
506
755
  this.notes = data.notes;
507
- this.mapKey = data.mapKey;
508
- this.badgeKey = data.badgeKey;
509
- this.badgePartialKey = data.badgePartialKey;
756
+ this.links = data.links ?? [];
510
757
  }
511
758
  }
512
759
 
513
760
  var __defProp$2 = Object.defineProperty;
514
761
  var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
515
762
  var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
516
- class VidiotMap {
763
+ class Mission {
517
764
  constructor(data) {
518
765
  /**
519
- * URL of the map image.
766
+ * Unique key used to reference this mission.
767
+ *
768
+ * Keys must be unique and can only contain lowercase letters, numbers and hyphens (`-`).
520
769
  */
521
- __publicField$2(this, "imageUrl");
770
+ __publicField$2(this, "key");
522
771
  /**
523
- * Name to display for the Vidiot map.
772
+ * The name of the mission as it appears from the contact.
773
+ *
774
+ * The name may be different when viewed in Ouroboros as a Flashback.
524
775
  */
525
776
  __publicField$2(this, "name");
526
777
  /**
527
- * List of Points of Interest labelled on the image.
778
+ * The type of mission... Story arc, task force, trial, etc.
528
779
  */
529
- __publicField$2(this, "pointsOfInterest");
530
- this.imageUrl = data.imageUrl;
531
- this.name = data.name;
532
- this.pointsOfInterest = data.pointsOfInterest?.map((data2) => new VidiotMapPointOfInterest(data2));
533
- }
534
- }
535
-
536
- var __defProp$1 = Object.defineProperty;
537
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
538
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
539
- class GameMap {
540
- constructor(data) {
780
+ __publicField$2(this, "type");
781
+ /**
782
+ * The character moralities that may accept the mission.
783
+ */
784
+ __publicField$2(this, "morality");
541
785
  /**
542
- * The database key for this map.
786
+ * The keys of any contacts that provide this mission.
543
787
  */
544
- __publicField$1(this, "key");
788
+ __publicField$2(this, "contactKeys");
545
789
  /**
546
- * The name of the map as it appears in-game.
790
+ * The level range this mission is available for.
547
791
  */
548
- __publicField$1(this, "name");
792
+ __publicField$2(this, "levelRange");
549
793
  /**
550
- * List of external links for this Map. Wiki, forums, etc.
794
+ * Freeform notes or tips about the mission.
551
795
  */
552
- __publicField$1(this, "links");
796
+ __publicField$2(this, "notes");
553
797
  /**
554
- * List of Vidiot Map assets for this map.
798
+ * List of external links. Wiki, forums, etc.
555
799
  */
556
- __publicField$1(this, "vidiotMaps");
800
+ __publicField$2(this, "links");
801
+ /**
802
+ * If the mission is available in Ouroboros as a Flashback.
803
+ */
804
+ __publicField$2(this, "flashback");
557
805
  this.key = new Key(data.key).value;
558
806
  this.name = data.name;
559
- this.links = data.links;
560
- this.vidiotMaps = data.vidiotMaps?.map((data2) => new VidiotMap(data2));
807
+ this.type = data.type;
808
+ this.morality = new MoralityList(coalesceToArray(data.morality));
809
+ this.contactKeys = coalesceToArray(data.contactKeys);
810
+ this.levelRange = data.levelRange;
811
+ this.notes = data.notes;
812
+ this.links = data.links ?? [];
813
+ this.flashback = createFlashback(data);
561
814
  }
562
815
  }
816
+ function createFlashback(data) {
817
+ if (!data.flashback) return void 0;
818
+ return {
819
+ id: data.flashback.id,
820
+ levelRange: data.flashback.levelRange ?? data.levelRange,
821
+ name: data.flashback.name ?? data.name,
822
+ morality: new MoralityList(coalesceToArray(data.flashback.morality ?? data.morality)),
823
+ notes: data.flashback.notes
824
+ };
825
+ }
563
826
 
564
- var __defProp = Object.defineProperty;
827
+ var __defProp$1 = Object.defineProperty;
565
828
  var __typeError = (msg) => {
566
829
  throw TypeError(msg);
567
830
  };
568
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
569
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
831
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
832
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
570
833
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
571
834
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
572
835
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
573
836
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
574
- var _archetypeIndex, _mapIndex, _badgeIndex;
837
+ var _archetypeIndex, _zoneIndex, _contactIndex, _missionIndex, _badgeIndex;
575
838
  class CohContentDatabase {
576
839
  /**
577
840
  * Initialize the database with a content bundle.
@@ -579,55 +842,84 @@ class CohContentDatabase {
579
842
  */
580
843
  constructor(bundle) {
581
844
  __privateAdd(this, _archetypeIndex, {});
582
- __privateAdd(this, _mapIndex, {});
845
+ __privateAdd(this, _zoneIndex, {});
846
+ __privateAdd(this, _contactIndex, {});
847
+ __privateAdd(this, _missionIndex, {});
583
848
  __privateAdd(this, _badgeIndex);
584
849
  /**
585
850
  * Metadata about the content bundle.
586
851
  */
587
- __publicField(this, "metadata");
852
+ __publicField$1(this, "metadata");
588
853
  /**
589
- * List of the game server names in this server group.
854
+ * List of the game server names.
855
+ *
590
856
  * Torchbearer, Excelsior, etc.
591
857
  */
592
- __publicField(this, "servers");
858
+ __publicField$1(this, "servers");
859
+ /**
860
+ * List of archetypes.
861
+ */
862
+ __publicField$1(this, "archetypes");
863
+ /**
864
+ * List of game zones.
865
+ */
866
+ __publicField$1(this, "zones");
593
867
  /**
594
- * List of archetypes available in this server group.
868
+ * List of contacts.
595
869
  */
596
- __publicField(this, "archetypes");
870
+ __publicField$1(this, "contacts");
597
871
  /**
598
- * List of game maps supported by this server group.
872
+ * List of missions.
599
873
  */
600
- __publicField(this, "maps");
874
+ __publicField$1(this, "missions");
601
875
  /**
602
- * List of badges available on this server group.
876
+ * List of badges.
603
877
  */
604
- __publicField(this, "badges");
878
+ __publicField$1(this, "badges");
605
879
  this.metadata = new BundleMetadata(bundle);
606
880
  this.servers = bundle.servers ?? [];
607
881
  this.archetypes = bundle.archetypes?.map((data) => {
608
- if (__privateGet(this, _archetypeIndex)[data.key] !== void 0) throw new Error(`Duplicate archetype key [${data.key}]`);
882
+ if (__privateGet(this, _archetypeIndex)[data.key] !== void 0) throw new Error(`Duplicate archetype key '${data.key}'`);
609
883
  const archetype = new Archetype(data);
610
884
  __privateGet(this, _archetypeIndex)[archetype.key] = archetype;
611
885
  return archetype;
612
886
  }) ?? [];
613
- this.maps = bundle.maps?.map((data) => {
614
- if (__privateGet(this, _mapIndex)[data.key] !== void 0) throw new Error(`Duplicate map key [${data.key}]`);
615
- const map = new GameMap(data);
616
- __privateGet(this, _mapIndex)[map.key] = map;
617
- return map;
887
+ this.zones = bundle.zones?.map((data) => {
888
+ if (__privateGet(this, _zoneIndex)[data.key] !== void 0) throw new Error(`Duplicate zone key '${data.key}'`);
889
+ const zone = new Zone(data);
890
+ __privateGet(this, _zoneIndex)[zone.key] = zone;
891
+ return zone;
892
+ }) ?? [];
893
+ this.contacts = bundle.contacts?.map((data) => {
894
+ if (__privateGet(this, _contactIndex)[data.key] !== void 0) throw new Error(`Duplicate contact key '${data.key}'`);
895
+ const contact = new Contact(data);
896
+ __privateGet(this, _contactIndex)[contact.key] = contact;
897
+ return contact;
898
+ }) ?? [];
899
+ this.missions = bundle.missions?.map((data) => {
900
+ if (__privateGet(this, _missionIndex)[data.key] !== void 0) throw new Error(`Duplicate mission key '${data.key}'`);
901
+ const mission = new Mission(data);
902
+ __privateGet(this, _missionIndex)[mission.key] = mission;
903
+ return mission;
618
904
  }) ?? [];
619
905
  this.badges = bundle.badges?.map((data) => new Badge(data)) ?? [];
620
- __privateSet(this, _badgeIndex, new BadgeIndex(this.badges, this.maps));
906
+ __privateSet(this, _badgeIndex, new BadgeIndex(this.badges));
621
907
  }
622
908
  getArchetype(key) {
623
- const result = __privateGet(this, _archetypeIndex)[key];
624
- if (result === void 0) throw new Error(`Unknown archetype key [${key}]`);
625
- return result;
909
+ if (!key) return void 0;
910
+ return __privateGet(this, _archetypeIndex)[key];
626
911
  }
627
- getMap(key) {
628
- const result = __privateGet(this, _mapIndex)[key];
629
- if (result === void 0) throw new Error(`Unknown map key [${key}]`);
630
- return result;
912
+ getZone(key) {
913
+ if (!key) return void 0;
914
+ return __privateGet(this, _zoneIndex)[key];
915
+ }
916
+ getContact(key) {
917
+ if (!key) return void 0;
918
+ return __privateGet(this, _contactIndex)[key];
919
+ }
920
+ getMission(key) {
921
+ if (!key) return void 0;
922
+ return __privateGet(this, _missionIndex)[key];
631
923
  }
632
924
  getBadge(key) {
633
925
  return __privateGet(this, _badgeIndex).getBadge(key);
@@ -643,20 +935,55 @@ class CohContentDatabase {
643
935
  }
644
936
  }
645
937
  _archetypeIndex = new WeakMap();
646
- _mapIndex = new WeakMap();
938
+ _zoneIndex = new WeakMap();
939
+ _contactIndex = new WeakMap();
940
+ _missionIndex = new WeakMap();
647
941
  _badgeIndex = new WeakMap();
648
942
 
943
+ var __defProp = Object.defineProperty;
944
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
945
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
946
+ class Location {
947
+ constructor(data) {
948
+ /**
949
+ * Key of the {@link Zone} that the location references.
950
+ */
951
+ __publicField(this, "zoneKey");
952
+ /**
953
+ * In-game `/loc` coordinates of the location.
954
+ */
955
+ __publicField(this, "coords");
956
+ /**
957
+ * The type of icon to use if the location appears on a map. (Typically the Vidiot map icon).
958
+ */
959
+ __publicField(this, "icon");
960
+ /**
961
+ * The text that should appear in the location icon. (Typically a number or symbol from the Vidiot map).
962
+ */
963
+ __publicField(this, "iconText");
964
+ this.zoneKey = data.zoneKey;
965
+ this.coords = data.coords;
966
+ this.icon = data.icon;
967
+ this.iconText = data.iconText;
968
+ }
969
+ }
970
+
649
971
  const CHANGELOG = [
650
972
  {
651
973
  version: "2.0.0",
652
974
  date: /* @__PURE__ */ new Date("2025-03-12"),
653
975
  description: `* Replaced redundant interfaces with their concrete equivalents.
654
976
  * Server groups are now referred to as 'forks'.
655
- * Replaced enums with union types.
656
- * \`IServerGroupData\` is now \`ContentBundle\` and each database instance is now designed to accept only a single server group.
977
+ * Replaced enums with union types and changed values to \`kebab-case\`.
978
+ * \`IServerGroupData\` is now \`ContentBundle\` and each database instance is now designed to accept only a single bundle.
979
+ * \`GameMap\` is now \`Zone\`.
657
980
  * Removed the \`serverGroup\` property from entities to simplify the object tree given that only a single context can exist per db now.
658
981
  * Added a simple indexing and search function for badge names, text and acquisition info.
659
- * Map and badge references now follow a standard Markdown link format with a \`badge://\` or \`map://\` protocol.
982
+ * Zone and badge references now follow a standard Markdown link format with a \`badge://\` or \`map://\` protocol.
983
+ * Badge partials are now known as badge requirements.
984
+ * Removed the \`VidiotMap\` API as it was never used or fleshed out properly.
985
+ * Added formal support for Missions and Contacts in badge requirements.
986
+ * Move exploration badge locations into badge requirement list.
660
987
  * Standardized pluralization of some field names (name, icon).
661
988
  * Combined \`settitle\` ids into a single tuple field.
662
989
  * Change from GNU to The Unlicense.
@@ -669,22 +996,5 @@ const CHANGELOG = [
669
996
  }
670
997
  ];
671
998
 
672
- function badgeUri(target) {
673
- const key = typeof target === "string" ? target : target.key;
674
- return `badge://${key}`;
675
- }
676
- function badgeLink(target) {
677
- const key = typeof target === "string" ? target : target.key;
678
- return `[${key}](${badgeUri(target)})`;
679
- }
680
- function mapUri(target) {
681
- const key = typeof target === "string" ? target : target.key;
682
- return `map://${key}`;
683
- }
684
- function mapLink(target) {
685
- const key = typeof target === "string" ? target : target.key;
686
- return `[${key}](${mapUri(target)})`;
687
- }
688
-
689
- export { ALIGNMENT, Alignments, Alternates, Archetype, BADGE_PARTIAL_TYPE, BADGE_TYPE, Badge, BadgeIndex, BadgePartial, BundleMetadata, CHANGELOG, CohContentDatabase, ENHANCEMENT_CATEGORY, GameMap, Key, PLAQUE_TYPE, SEX, VidiotMap, VidiotMapPointOfInterest, badgeLink, badgeUri, mapLink, mapUri };
999
+ export { ALIGNMENT, AlignmentList, Alternates, Archetype, BADGE_REQUIREMENT_TYPE, BADGE_TYPE, Badge, BadgeIndex, BadgeRequirement, BundleMetadata, CHANGELOG, CohContentDatabase, Contact, ENHANCEMENT_CATEGORY, Key, Location, MISSION_TYPE, MORALITY, Mission, MoralityList, SEX, Zone, badgeLink, badgeUri, coalesceToArray, compareAlignment, compareByDefaultName, compareByZoneKey, compareSex, contactLink, contactUri, missionLink, missionUri, zoneLink, zoneUri };
690
1000
  //# sourceMappingURL=coh-content-db.mjs.map