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

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 (51) hide show
  1. package/README.md +4 -4
  2. package/dist/coh-content-db.d.ts +203 -156
  3. package/dist/coh-content-db.js +263 -197
  4. package/dist/coh-content-db.js.map +1 -1
  5. package/dist/coh-content-db.mjs +256 -191
  6. package/dist/coh-content-db.mjs.map +1 -1
  7. package/package.json +1 -1
  8. package/src/main/api/badge-data.ts +16 -9
  9. package/src/main/api/{badge-partial-data.ts → badge-requirement-data.ts} +24 -8
  10. package/src/main/api/badge-requirement-type.ts +11 -0
  11. package/src/main/api/contact-data.ts +46 -0
  12. package/src/main/api/content-bundle.ts +10 -4
  13. package/src/main/api/zone-data.ts +20 -0
  14. package/src/main/changelog.ts +5 -1
  15. package/src/main/db/badge-index.ts +17 -11
  16. package/src/main/db/{badge-partial.ts → badge-requirement.ts} +30 -11
  17. package/src/main/db/badge-search-options.ts +2 -2
  18. package/src/main/db/badge.ts +48 -36
  19. package/src/main/db/bundle-metadata.ts +3 -3
  20. package/src/main/db/coh-content-database.ts +51 -18
  21. package/src/main/db/contact.ts +59 -0
  22. package/src/main/db/zone.ts +28 -0
  23. package/src/main/index.ts +8 -10
  24. package/src/main/util.ts +44 -13
  25. package/src/test/api/badge-data.fixture.ts +9 -7
  26. package/src/test/api/badge-requirement-data.fixture.ts +17 -0
  27. package/src/test/api/badge-requirement-type.test.ts +31 -0
  28. package/src/test/api/contact-data.fixture.ts +13 -0
  29. package/src/test/api/content-bundle.fixture.ts +2 -2
  30. package/src/test/api/content-bundle.test.ts +1 -1
  31. package/src/test/api/zone-data.fixture.ts +8 -0
  32. package/src/test/db/badge-index.test.ts +73 -41
  33. package/src/test/db/badge-requirement.test.ts +180 -0
  34. package/src/test/db/badge.test.ts +190 -15
  35. package/src/test/db/coh-content-database.test.ts +110 -18
  36. package/src/test/db/contact.test.ts +96 -0
  37. package/src/test/db/zone.test.ts +36 -0
  38. package/src/test/index.test.ts +4 -2
  39. package/src/test/util.test.ts +59 -22
  40. package/src/main/api/badge-partial-type.ts +0 -8
  41. package/src/main/api/game-map-data.ts +0 -26
  42. package/src/main/api/vidiot-map-data.ts +0 -18
  43. package/src/main/api/vidiot-map-point-of-interest-data.ts +0 -30
  44. package/src/main/db/game-map.ts +0 -33
  45. package/src/main/db/vidiot-map-point-of-interest.ts +0 -39
  46. package/src/main/db/vidiot-map.ts +0 -25
  47. package/src/test/api/badge-partial-data.fixture.ts +0 -17
  48. package/src/test/api/badge-partial-type.test.ts +0 -31
  49. package/src/test/api/game-map-data.fixture.ts +0 -10
  50. package/src/test/api/vidiot-map-point-of-interest.fixture.ts +0 -10
  51. package/src/test/api/vidiot-map.fixture.ts +0 -9
@@ -1,25 +1,26 @@
1
- import { BadgePartialData } from '../api/badge-partial-data'
1
+ import { BadgeRequirementData } from '../api/badge-requirement-data'
2
2
  import { PlaqueType } from '../api/plaque-type'
3
- import { BadgePartialType } from '../api/badge-partial-type'
3
+ import { BadgeRequirementType } from '../api/badge-requirement-type'
4
4
  import { EnhancementCategory } from '../api/enhancement-category'
5
5
  import { Key } from './key'
6
6
  import { MarkdownString } from '../api/markdown-string'
7
+ import { Link } from '../api/link'
7
8
 
8
- export class BadgePartial {
9
+ export class BadgeRequirement {
9
10
  /**
10
11
  * Key.
11
12
  */
12
13
  readonly key: string
13
14
 
14
15
  /**
15
- * Type of partial.
16
+ * Type of requirement.
16
17
  */
17
- readonly type: BadgePartialType
18
+ readonly type: BadgeRequirementType
18
19
 
19
20
  /**
20
- * Map the partial is located on.
21
+ * Zone the requirement is located in.
21
22
  */
22
- readonly mapKey?: string
23
+ readonly zoneKey?: string
23
24
 
24
25
  /**
25
26
  * /loc coordinates.
@@ -37,15 +38,25 @@ export class BadgePartial {
37
38
  readonly plaqueInscription?: string
38
39
 
39
40
  /**
40
- * The number or letter the partial appears as on Vidiot Maps.
41
+ * The number or letter the plaque appears as on Vidiot Maps.
41
42
  */
42
43
  readonly vidiotMapKey?: string
43
44
 
44
45
  /**
45
- * The badge required for this partial.
46
+ * The key of the badge for this requirement.
46
47
  */
47
48
  readonly badgeKey?: string
48
49
 
50
+ /**
51
+ * Mission name.
52
+ */
53
+ readonly missionName?: string
54
+
55
+ /**
56
+ * {@link Contact} key for the story arc.
57
+ */
58
+ readonly contactKey?: string
59
+
49
60
  /**
50
61
  * Level of the invention required.
51
62
  */
@@ -66,18 +77,26 @@ export class BadgePartial {
66
77
  */
67
78
  readonly notes?: MarkdownString
68
79
 
69
- constructor(data: BadgePartialData) {
80
+ /**
81
+ * List of external links. Wiki, forums, etc.
82
+ */
83
+ readonly links: Link[]
84
+
85
+ constructor(data: BadgeRequirementData) {
70
86
  this.key = new Key(data.key).value
71
87
  this.type = data.type
72
- this.mapKey = data.mapKey
88
+ this.zoneKey = data.zoneKey
73
89
  this.loc = data.loc
74
90
  this.plaqueType = data.plaqueType
75
91
  this.plaqueInscription = data.plaqueInscription
76
92
  this.vidiotMapKey = data.vidiotMapKey
77
93
  this.badgeKey = data.badgeKey
94
+ this.missionName = data.missionName
95
+ this.contactKey = data.contactKey
78
96
  this.inventionLevel = data.inventionLevel
79
97
  this.inventionTypes = data.inventionTypes
80
98
  this.inventionCount = data.inventionCount
81
99
  this.notes = data.notes
100
+ this.links = data.links ?? []
82
101
  }
83
102
  }
@@ -25,7 +25,7 @@ export interface BadgeSearchOptions {
25
25
  */
26
26
  filter?: {
27
27
  type?: BadgeType
28
- mapKey?: string
28
+ zoneKey?: string
29
29
  alignment?: Alignment
30
30
  }
31
31
 
@@ -35,7 +35,7 @@ export interface BadgeSearchOptions {
35
35
  * Badges are assumed to be in canonical order in the content bundle, and should match the in-game display order.
36
36
  */
37
37
  sort?: {
38
- by?: 'CANONICAL' | 'BADGE_NAME' | 'MAP_NAME'
38
+ by?: 'CANONICAL' | 'BADGE_NAME' | 'ZONE_NAME'
39
39
  dir?: 'ASC' | 'DESC'
40
40
  }
41
41
 
@@ -1,14 +1,14 @@
1
1
  import { BadgeType } from '../api/badge-type'
2
2
  import { Link } from '../api/link'
3
3
  import { BadgeData } from '../api/badge-data'
4
- import { BadgePartial } from './badge-partial'
4
+ import { BadgeRequirement } from './badge-requirement'
5
5
  import { Key } from './key'
6
6
  import { Alternates } from './alternates'
7
7
  import { Alignments } from './alignments'
8
8
  import { MarkdownString } from '../api/markdown-string'
9
9
 
10
10
  export class Badge {
11
- readonly #partialsIndex: Record<string, BadgePartial> = {}
11
+ readonly #requirementsIndex: Record<string, BadgeRequirement> = {}
12
12
 
13
13
  /**
14
14
  * The database key for this badge.
@@ -38,7 +38,7 @@ export class Badge {
38
38
  readonly badgeText: Alternates<string>
39
39
 
40
40
  /**
41
- * Description of how to acquire the badge.
41
+ * Short description of how to acquire the badge. Detailed instructions will be in the notes field.
42
42
  */
43
43
  readonly acquisition?: MarkdownString
44
44
 
@@ -55,22 +55,22 @@ export class Badge {
55
55
  readonly notes?: MarkdownString
56
56
 
57
57
  /**
58
- * List of external links for this Badge. Wiki, forums, etc.
58
+ * List of external links. Wiki, forums, etc.
59
59
  */
60
- readonly links?: Link[]
60
+ readonly links: Link[]
61
61
 
62
62
  /**
63
- * For exploration badges, the key of the {@link GameMap} that this badge is found on.
63
+ * For exploration badges, the key of the {@link Zone} that this badge is found on.
64
64
  */
65
- readonly mapKey?: string
65
+ readonly zoneKey?: string
66
66
 
67
67
  /**
68
- * For exploration badges, the `/loc` coordinates of the badge on the in-game map.
68
+ * For exploration badges, the `/loc` coordinates of the badge.
69
69
  */
70
70
  readonly loc?: [number, number, number]
71
71
 
72
72
  /**
73
- * For badges that appear on a Vidiot Map, the number or letter the badge appears as.
73
+ * For plaques that appear on a Vidiot Map, the number or letter the badge appears as.
74
74
  */
75
75
  readonly vidiotMapKey?: string
76
76
 
@@ -94,43 +94,55 @@ export class Badge {
94
94
  readonly effect?: MarkdownString
95
95
 
96
96
  /**
97
- * 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.
97
+ * Represents the layered requirements for badges with multiple fulfillment steps,
98
+ * such as visiting plaques for history badges or collecting other badges.
99
+ *
100
+ * The outer array represents groups of requirements evaluated with OR logic —
101
+ * fulfilling any group satisfies the badge.
102
+ *
103
+ * Each inner array represents individual requirements evaluated with AND logic —
104
+ * all conditions in the group must be met.
98
105
  */
99
- readonly partials?: BadgePartial[]
106
+ readonly requirements?: BadgeRequirement[][]
100
107
 
101
108
  /**
102
109
  * 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.
103
110
  */
104
111
  readonly ignoreInTotals: boolean
105
112
 
106
- constructor(data: BadgeData) {
107
- this.key = new Key(data.key).value
108
- this.type = data.type
109
- this.name = new Alternates(data.name)
110
- this.alignment = new Alignments(data.alignment)
111
- this.badgeText = new Alternates(data.badgeText ?? [])
112
- this.acquisition = data.acquisition
113
- this.icon = new Alternates(data.icon ?? [])
114
- this.notes = data.notes
115
- this.links = data.links
116
- this.mapKey = data.mapKey
117
- this.loc = data.loc
118
- this.effect = data.effect
119
- this.vidiotMapKey = data.vidiotMapKey
120
- this.setTitle = data.setTitle
121
- this.ignoreInTotals = data.ignoreInTotals ?? false
122
-
123
- this.partials = data.partials?.map((data) => {
124
- if (this.#partialsIndex[data.key] !== undefined) throw new Error(`Duplicate badge partial key [${data.key}]`)
125
- const badge = new BadgePartial(data)
126
- this.#partialsIndex[badge.key] = badge
127
- return badge
113
+ constructor(badgeData: BadgeData) {
114
+ this.key = new Key(badgeData.key).value
115
+ this.type = badgeData.type
116
+ this.name = new Alternates(badgeData.name)
117
+ this.alignment = new Alignments(badgeData.alignment)
118
+ this.badgeText = new Alternates(badgeData.badgeText ?? [])
119
+ this.acquisition = badgeData.acquisition
120
+ this.icon = new Alternates(badgeData.icon ?? [])
121
+ this.notes = badgeData.notes
122
+ this.links = badgeData.links ?? []
123
+ this.zoneKey = badgeData.zoneKey
124
+ this.loc = badgeData.loc
125
+ this.effect = badgeData.effect
126
+ this.vidiotMapKey = badgeData.vidiotMapKey
127
+ this.setTitle = badgeData.setTitle
128
+ this.ignoreInTotals = badgeData.ignoreInTotals ?? false
129
+
130
+ this.requirements = badgeData.requirements?.map((groups, index) => {
131
+ const existingKeysInGroup = new Set<string>()
132
+ return groups.map((requirementData) => {
133
+ if (existingKeysInGroup.has(requirementData.key)) throw new Error(`Duplicate badge requirement key [${badgeData.key}:${requirementData.key}] in group [${index + 1}]`)
134
+ existingKeysInGroup.add(requirementData.key)
135
+
136
+ const badge = new BadgeRequirement(requirementData)
137
+ this.#requirementsIndex[badge.key] = badge
138
+ return badge
139
+ })
128
140
  })
129
141
  }
130
142
 
131
- getPartial(key: string): BadgePartial {
132
- const result = this.#partialsIndex[key]
133
- if (result === undefined) throw new Error(`Unknown badge partial key [${key}]`)
143
+ getRequirement(key: string): BadgeRequirement {
144
+ const result = this.#requirementsIndex[key]
145
+ if (result === undefined) throw new Error(`Unknown badge requirement key [${key}]`)
134
146
  return result
135
147
  }
136
148
  }
@@ -5,12 +5,12 @@ import { MarkdownString } from '../api/markdown-string'
5
5
 
6
6
  export class BundleMetadata {
7
7
  /**
8
- * Name of the server group.
8
+ * Name of the content bundle.
9
9
  */
10
10
  readonly name: string
11
11
 
12
12
  /**
13
- * Description of the server group.
13
+ * Description of the fork.
14
14
  */
15
15
  readonly description?: MarkdownString
16
16
 
@@ -20,7 +20,7 @@ export class BundleMetadata {
20
20
  readonly repository?: string
21
21
 
22
22
  /**
23
- * List of external links for this Server Group. Wiki, forums, etc.
23
+ * List of external links. Wiki, forums, etc.
24
24
  */
25
25
  readonly links: Link[]
26
26
 
@@ -1,15 +1,17 @@
1
1
  import { ContentBundle } from '../api/content-bundle'
2
2
  import { Archetype } from './archetype'
3
- import { GameMap } from './game-map'
3
+ import { Zone } from './zone'
4
4
  import { Badge } from './badge'
5
5
  import { BundleMetadata } from './bundle-metadata'
6
6
  import { BadgeIndex } from './badge-index'
7
7
  import { BadgeSearchOptions } from './badge-search-options'
8
8
  import { Paged } from './paged'
9
+ import { Contact } from './contact'
9
10
 
10
11
  export class CohContentDatabase {
11
12
  readonly #archetypeIndex: Record<string, Archetype> = {}
12
- readonly #mapIndex: Record<string, GameMap> = {}
13
+ readonly #zoneIndex: Record<string, Zone> = {}
14
+ readonly #contactIndex: Record<string, Contact> = {}
13
15
  readonly #badgeIndex: BadgeIndex
14
16
 
15
17
  /**
@@ -18,23 +20,29 @@ export class CohContentDatabase {
18
20
  readonly metadata: BundleMetadata
19
21
 
20
22
  /**
21
- * List of the game server names in this server group.
23
+ * List of the game server names.
24
+ *
22
25
  * Torchbearer, Excelsior, etc.
23
26
  */
24
27
  readonly servers: string[]
25
28
 
26
29
  /**
27
- * List of archetypes available in this server group.
30
+ * List of archetypes.
28
31
  */
29
32
  readonly archetypes: Archetype[]
30
33
 
31
34
  /**
32
- * List of game maps supported by this server group.
35
+ * List of game zones.
33
36
  */
34
- readonly maps: GameMap[]
37
+ readonly zones: Zone[]
35
38
 
36
39
  /**
37
- * List of badges available on this server group.
40
+ * List of contacts.
41
+ */
42
+ readonly contacts: Contact[]
43
+
44
+ /**
45
+ * List of badges.
38
46
  */
39
47
  readonly badges: Badge[]
40
48
 
@@ -47,39 +55,64 @@ export class CohContentDatabase {
47
55
  this.servers = bundle.servers ?? []
48
56
 
49
57
  this.archetypes = bundle.archetypes?.map((data) => {
50
- if (this.#archetypeIndex[data.key] !== undefined) throw new Error(`Duplicate archetype key [${data.key}]`)
58
+ if (this.#archetypeIndex[data.key] !== undefined) throw new Error(`Duplicate archetype key '${data.key}'`)
51
59
  const archetype = new Archetype(data)
52
60
  this.#archetypeIndex[archetype.key] = archetype
53
61
  return archetype
54
62
  }) ?? []
55
63
 
56
- this.maps = bundle.maps?.map((data) => {
57
- if (this.#mapIndex[data.key] !== undefined) throw new Error(`Duplicate map key [${data.key}]`)
58
- const map = new GameMap(data)
59
- this.#mapIndex[map.key] = map
60
- return map
64
+ this.zones = bundle.zones?.map((data) => {
65
+ if (this.#zoneIndex[data.key] !== undefined) throw new Error(`Duplicate zone key '${data.key}'`)
66
+ const zone = new Zone(data)
67
+ this.#zoneIndex[zone.key] = zone
68
+ return zone
69
+ }) ?? []
70
+
71
+ this.contacts = bundle.contacts?.map((data) => {
72
+ if (this.#contactIndex[data.key] !== undefined) throw new Error(`Duplicate contact key '${data.key}'`)
73
+ const contact = new Contact(data)
74
+ this.#contactIndex[contact.key] = contact
75
+ return contact
61
76
  }) ?? []
62
77
 
63
78
  this.badges = bundle.badges?.map(data => new Badge(data)) ?? []
64
- this.#badgeIndex = new BadgeIndex(this.badges, this.maps)
79
+ this.#badgeIndex = new BadgeIndex(this.badges, this.zones)
65
80
  }
66
81
 
67
82
  getArchetype(key: string): Archetype {
68
83
  const result = this.#archetypeIndex[key]
69
- if (result === undefined) throw new Error(`Unknown archetype key [${key}]`)
84
+ if (result === undefined) throw new Error(`Unknown archetype key '${key}'`)
85
+ return result
86
+ }
87
+
88
+ getZone(key: string): Zone {
89
+ const result = this.#zoneIndex[key]
90
+ if (result === undefined) throw new Error(`Unknown zone key '${key}'`)
70
91
  return result
71
92
  }
72
93
 
73
- getMap(key: string): GameMap {
74
- const result = this.#mapIndex[key]
75
- if (result === undefined) throw new Error(`Unknown map key [${key}]`)
94
+ getContact(key: string): Contact {
95
+ const result = this.#contactIndex[key]
96
+ if (result === undefined) throw new Error(`Unknown contact key '${key}'`)
76
97
  return result
77
98
  }
78
99
 
100
+ zoneExists(key: string): boolean {
101
+ return !!this.#zoneIndex[key]
102
+ }
103
+
104
+ contactExists(key: string): boolean {
105
+ return !!this.#contactIndex[key]
106
+ }
107
+
79
108
  getBadge(key: string): Badge {
80
109
  return this.#badgeIndex.getBadge(key)
81
110
  }
82
111
 
112
+ badgeExists(key: string): boolean {
113
+ return this.#badgeIndex.badgeExists(key)
114
+ }
115
+
83
116
  /**
84
117
  * Search, sort and filter the badge list.
85
118
  * This is a fairly brute-forced approach and will not be as performant as loading the badge data into a traditional
@@ -0,0 +1,59 @@
1
+ import { Link } from '../api/link'
2
+ import { Key } from './key'
3
+ import { MarkdownString } from '../api/markdown-string'
4
+ import { ContactData } from '../api/contact-data'
5
+
6
+ export class Contact {
7
+ /**
8
+ * Unique key used to reference this contact.
9
+ *
10
+ * Keys can only contain lowercase letters, numbers and hyphens (`-`).
11
+ */
12
+ readonly key: string
13
+
14
+ /**
15
+ * The name of this contact.
16
+ */
17
+ readonly name: string
18
+
19
+ /**
20
+ * The contact's title.
21
+ */
22
+ readonly title?: string
23
+
24
+ /**
25
+ * The zone this character is located in.
26
+ */
27
+ readonly zoneKey?: string
28
+
29
+ /**
30
+ * The `/loc` coordinates of the contact.
31
+ */
32
+ readonly loc?: [number, number, number]
33
+
34
+ /**
35
+ * The level range this contact will offer missions for.
36
+ */
37
+ readonly levelRange?: [number, number?]
38
+
39
+ /**
40
+ * Freeform notes or tips about the contact.
41
+ */
42
+ readonly notes?: MarkdownString
43
+
44
+ /**
45
+ * List of external links. Wiki, forums, etc.
46
+ */
47
+ readonly links: Link[]
48
+
49
+ constructor(contactData: ContactData) {
50
+ this.key = new Key(contactData.key).value
51
+ this.name = contactData.name
52
+ this.title = contactData.title
53
+ this.zoneKey = contactData.zoneKey
54
+ this.loc = contactData.loc
55
+ this.levelRange = contactData.levelRange
56
+ this.notes = contactData.notes
57
+ this.links = contactData.links ?? []
58
+ }
59
+ }
@@ -0,0 +1,28 @@
1
+ import { Link } from '../api/link'
2
+ import { ZoneData } from '../api/zone-data'
3
+ import { Key } from './key'
4
+
5
+ export class Zone {
6
+ /**
7
+ * Unique key used to reference this zone.
8
+ *
9
+ * Keys can only contain lowercase letters, numbers and hyphens (`-`).
10
+ */
11
+ readonly key: string
12
+
13
+ /**
14
+ * The name of the zone as it appears in-game.
15
+ */
16
+ readonly name: string
17
+
18
+ /**
19
+ * List of external links. Wiki, forums, etc.
20
+ */
21
+ readonly links: Link[]
22
+
23
+ constructor(data: ZoneData) {
24
+ this.key = new Key(data.key).value
25
+ this.name = data.name
26
+ this.links = data.links ?? []
27
+ }
28
+ }
package/src/main/index.ts CHANGED
@@ -3,19 +3,18 @@ export * from './api/alignment'
3
3
  export * from './api/alternate-data'
4
4
  export * from './api/archetype-data'
5
5
  export * from './api/badge-data'
6
- export * from './api/badge-partial-data'
7
- export * from './api/badge-partial-type'
6
+ export * from './api/badge-requirement-data'
7
+ export * from './api/badge-requirement-type'
8
8
  export * from './api/badge-type'
9
9
  export * from './api/change'
10
+ export * from './api/contact-data'
11
+ export * from './api/content-bundle'
10
12
  export * from './api/enhancement-category'
11
- export * from './api/game-map-data'
12
13
  export * from './api/link'
13
14
  export * from './api/markdown-string'
14
15
  export * from './api/plaque-type'
15
- export * from './api/content-bundle'
16
16
  export * from './api/sex'
17
- export * from './api/vidiot-map-data'
18
- export * from './api/vidiot-map-point-of-interest-data'
17
+ export * from './api/zone-data'
19
18
 
20
19
  // DB
21
20
  export * from './db/alignments'
@@ -23,15 +22,14 @@ export * from './db/alternates'
23
22
  export * from './db/archetype'
24
23
  export * from './db/badge'
25
24
  export * from './db/badge-index'
26
- export * from './db/badge-partial'
25
+ export * from './db/badge-requirement'
27
26
  export * from './db/badge-search-options'
28
27
  export * from './db/bundle-metadata'
29
28
  export * from './db/coh-content-database'
30
- export * from './db/game-map'
29
+ export * from './db/contact'
31
30
  export * from './db/key'
32
31
  export * from './db/paged'
33
- export * from './db/vidiot-map'
34
- export * from './db/vidiot-map-point-of-interest'
32
+ export * from './db/zone'
35
33
 
36
34
  // ROOT
37
35
  export { CHANGELOG } from './changelog'
package/src/main/util.ts CHANGED
@@ -1,3 +1,10 @@
1
+ import { BadgeData } from './api/badge-data'
2
+ import { Badge } from './db/badge'
3
+ import { ZoneData } from './api/zone-data'
4
+ import { Zone } from './db/zone'
5
+ import { Contact } from './db/contact'
6
+ import { ContactData } from './api/contact-data'
7
+
1
8
  /**
2
9
  * Returns the URI of the given badge that can be used in {@link MarkdownString} links.
3
10
  *
@@ -5,7 +12,7 @@
5
12
  *
6
13
  * @param target The badge or badge key to target.
7
14
  */
8
- export function badgeUri(target: string | { key: string }): string {
15
+ export function badgeUri(target: string | Badge | BadgeData): string {
9
16
  const key = typeof target === 'string' ? target : target.key
10
17
  return `badge://${key}`
11
18
  }
@@ -15,33 +22,57 @@ export function badgeUri(target: string | { key: string }): string {
15
22
  *
16
23
  * Link format: `[<key>](badge://<key>)`
17
24
  *
18
- * @param target The badge or badge key to target.
25
+ * @param target The {@link Badge} or badge key to target.
19
26
  */
20
- export function badgeLink(target: string | { key: string }): string {
27
+ export function badgeLink(target: string | Badge | BadgeData): string {
21
28
  const key = typeof target === 'string' ? target : target.key
22
29
  return `[${key}](${badgeUri(target)})`
23
30
  }
24
31
 
25
32
  /**
26
- * Returns the URI of the given map that can be used in {@link MarkdownString} links.
33
+ * Returns the URI of the given contact that can be used in {@link MarkdownString} links.
34
+ *
35
+ * URI format: `contact://<key>`
36
+ *
37
+ * @param target The {@link Contact} or contact key to target.
38
+ */
39
+ export function contactUri(target: string | Contact | ContactData): string {
40
+ const key = typeof target === 'string' ? target : target.key
41
+ return `contact://${key}`
42
+ }
43
+
44
+ /**
45
+ * Returns a {@link MarkdownString} link to the given contact.
46
+ *
47
+ * Link format: `[<key>](contact://<key>)`
48
+ *
49
+ * @param target The {@link Contact} or contact key to target.
50
+ */
51
+ export function contactLink(target: string | Contact | ContactData): string {
52
+ const key = typeof target === 'string' ? target : target.key
53
+ return `[${key}](${contactUri(target)})`
54
+ }
55
+
56
+ /**
57
+ * Returns the URI of the given zone that can be used in {@link MarkdownString} links.
27
58
  *
28
- * URI format: `map://<key>`
59
+ * URI format: `zone://<key>`
29
60
  *
30
- * @param target The {@link GameMap} or map key to target.
61
+ * @param target The {@link Zone} or zone key to target.
31
62
  */
32
- export function mapUri(target: string | { key: string }): string {
63
+ export function zoneUri(target: string | Zone | ZoneData): string {
33
64
  const key = typeof target === 'string' ? target : target.key
34
- return `map://${key}`
65
+ return `zone://${key}`
35
66
  }
36
67
 
37
68
  /**
38
- * Returns a {@link MarkdownString} link to the given map.
69
+ * Returns a {@link MarkdownString} link to the given zone.
39
70
  *
40
- * Link format: `[<key>](map://<key>)`
71
+ * Link format: `[<key>](zone://<key>)`
41
72
  *
42
- * @param target The map or map key to target.
73
+ * @param target The {@link Zone} or zone key to target.
43
74
  */
44
- export function mapLink(target: string | { key: string }): string {
75
+ export function zoneLink(target: string | Zone | ZoneData): string {
45
76
  const key = typeof target === 'string' ? target : target.key
46
- return `[${key}](${mapUri(target)})`
77
+ return `[${key}](${zoneUri(target)})`
47
78
  }
@@ -1,6 +1,6 @@
1
1
  import { defineFixture } from 'efate'
2
2
  import { ALIGNMENT, BADGE_TYPE, BadgeData } from '../../main'
3
- import { badgePartialDataFixture } from './badge-partial-data.fixture'
3
+ import { badgeRequirementDataFixture } from './badge-requirement-data.fixture'
4
4
 
5
5
  export const badgeDataFixture = defineFixture<BadgeData>((t) => {
6
6
  t.key.as(index => `badge-${index}`)
@@ -9,14 +9,16 @@ export const badgeDataFixture = defineFixture<BadgeData>((t) => {
9
9
  t.alignment.pickFrom([...ALIGNMENT])
10
10
  t.badgeText?.as(index => [{ value: `This is badge ${index}` }])
11
11
  t.acquisition?.asLoremIpsum()
12
- t.icon?.asArray([{ value: 'https://nouri.org' }])
12
+ t.icon?.as(() => [{ value: 'https://nouri.org' }])
13
13
  t.notes?.asLoremIpsum()
14
- t.links?.asArray([{ href: 'https://nouri.org' }])
15
- t.mapKey?.asString()
16
- t.loc?.asArray()
14
+ t.links?.as(() => [{ href: 'https://nouri.org' }])
15
+ t.zoneKey?.asString()
16
+ t.loc?.as(index => [index, index, index])
17
17
  t.vidiotMapKey?.asString()
18
- t.setTitle?.asArray({ length: 2 })
18
+ t.setTitle?.as((index) => {
19
+ return { id: index }
20
+ })
19
21
  t.effect?.asString()
20
- t.partials?.arrayOfFixture({ fixture: badgePartialDataFixture })
22
+ t.requirements?.as(() => [[badgeRequirementDataFixture]])
21
23
  t.ignoreInTotals?.asBoolean()
22
24
  })
@@ -0,0 +1,17 @@
1
+ import { defineFixture } from 'efate'
2
+ import { BADGE_REQUIREMENT_TYPE, BadgeRequirementData, ENHANCEMENT_CATEGORY, PLAQUE_TYPE } from '../../main'
3
+
4
+ export const badgeRequirementDataFixture = defineFixture<BadgeRequirementData>((t) => {
5
+ t.key.as(index => `badge-requirement-${index}`)
6
+ t.type.pickFrom([...BADGE_REQUIREMENT_TYPE])
7
+ t.zoneKey?.asString()
8
+ t.loc?.as(index => [index, index, index])
9
+ t.plaqueType?.pickFrom([...PLAQUE_TYPE])
10
+ t.plaqueInscription?.asLoremIpsum()
11
+ t.vidiotMapKey?.asString()
12
+ t.badgeKey?.as(index => `badge-${index}`)
13
+ t.inventionLevel?.asNumber()
14
+ t.inventionTypes?.pickFrom([...ENHANCEMENT_CATEGORY])
15
+ t.inventionCount?.asNumber()
16
+ t.notes?.asLoremIpsum()
17
+ })