coh-content-db 2.0.0-rc.2 → 2.0.0-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +10 -11
- package/.github/workflows/build.yml +4 -2
- package/.github/workflows/pull-request.yml +1 -1
- package/.github/workflows/release.yml +1 -1
- package/CHANGELOG.md +47 -0
- package/README.md +77 -32
- package/dist/coh-content-db.d.ts +755 -290
- package/dist/coh-content-db.js +1028 -358
- package/dist/coh-content-db.js.map +1 -1
- package/dist/coh-content-db.mjs +998 -349
- package/dist/coh-content-db.mjs.map +1 -1
- package/eslint.config.mjs +1 -0
- package/jest.config.mjs +1 -0
- package/package.json +14 -14
- package/src/main/api/alignment.ts +18 -2
- package/src/main/api/badge-data.ts +29 -51
- package/src/main/api/badge-requirement-data.ts +64 -0
- package/src/main/api/badge-requirement-type.ts +32 -0
- package/src/main/api/badge-type.ts +15 -15
- package/src/main/api/bundle-data.ts +47 -0
- package/src/main/api/bundle-header-data.ts +44 -0
- package/src/main/api/contact-data.ts +49 -0
- package/src/main/api/enhancement-category.ts +26 -26
- package/src/main/api/level-range-data.ts +4 -0
- package/src/main/api/location-data.ts +28 -0
- package/src/main/api/markdown-string.ts +4 -0
- package/src/main/api/mission-data.ts +57 -0
- package/src/main/api/mission-flashback-data.ts +31 -0
- package/src/main/api/mission-type.ts +2 -0
- package/src/main/api/morality.ts +49 -0
- package/src/main/api/set-title-data.ts +4 -0
- package/src/main/api/sex.ts +8 -1
- package/src/main/api/variant-context.ts +11 -0
- package/src/main/api/variant-data.ts +22 -0
- package/src/main/api/zone-data.ts +44 -0
- package/src/main/api/zone-type.ts +59 -0
- package/src/main/db/abstract-index.ts +37 -0
- package/src/main/db/alignment-list.ts +54 -0
- package/src/main/db/badge-index.ts +83 -0
- package/src/main/db/badge-requirement.ts +81 -0
- package/src/main/db/badge-search-options.ts +52 -0
- package/src/main/db/badge.ts +97 -74
- package/src/main/db/bundle-header.ts +52 -0
- package/src/main/db/coh-content-database.ts +123 -14
- package/src/main/db/contact.ts +63 -0
- package/src/main/db/level-range.ts +15 -0
- package/src/main/db/location.ts +30 -0
- package/src/main/db/mission.ts +108 -0
- package/src/main/db/morality-list.ts +99 -0
- package/src/main/db/paged.ts +11 -0
- package/src/main/db/set-title-ids.ts +10 -0
- package/src/main/db/variants.ts +84 -0
- package/src/main/db/zone.ts +57 -0
- package/src/main/index.ts +33 -18
- package/src/main/util/coalesce-to-array.ts +13 -0
- package/src/main/util/links.ts +104 -0
- package/src/main/util/to-date.ts +9 -0
- package/src/test/api/alignment.test.ts +38 -4
- package/src/test/api/badge-data.fixture.ts +2 -15
- package/src/test/api/badge-data.test.ts +5 -4
- package/src/test/api/badge-requirement-data.fixture.ts +7 -0
- package/src/test/api/badge-requirement-type.test.ts +31 -0
- package/src/test/api/badge-type.test.ts +5 -5
- package/src/test/api/bundle-data.fixture.ts +7 -0
- package/src/test/api/bundle-header-data.fixture.ts +8 -0
- package/src/test/api/contact-data.fixture.ts +7 -0
- package/src/test/api/enhancement-category.test.ts +5 -5
- package/src/test/api/mission-data.fixture.ts +12 -0
- package/src/test/api/morality.test.ts +31 -0
- package/src/test/api/sex.test.ts +33 -1
- package/src/test/api/zone-data.fixture.ts +9 -0
- package/src/test/db/abstract-index.test.ts +55 -0
- package/src/test/db/alignment-list.test.ts +200 -0
- package/src/test/db/badge-index.test.ts +653 -0
- package/src/test/db/badge-requirement.test.ts +145 -0
- package/src/test/db/badge.test.ts +416 -14
- package/src/test/db/bundle-header.test.ts +89 -0
- package/src/test/db/coh-content-database.test.ts +265 -24
- package/src/test/db/contact.test.ts +98 -0
- package/src/test/db/level-range.test.ts +47 -0
- package/src/test/db/location.test.ts +51 -0
- package/src/test/db/mission.test.ts +173 -0
- package/src/test/db/morality-list.test.ts +457 -0
- package/src/test/db/set-title-ids.test.ts +19 -0
- package/src/test/db/variants.test.ts +188 -0
- package/src/test/db/zone.test.ts +81 -0
- package/src/test/integration.test.ts +16 -0
- package/src/test/util/coalese-to-array.test.ts +17 -0
- package/src/test/util/links.test.ts +149 -0
- package/src/test/util/to-date.test.ts +15 -0
- package/src/main/api/alternate-data.ts +0 -22
- package/src/main/api/badge-partial-data.ts +0 -65
- package/src/main/api/badge-partial-type.ts +0 -8
- package/src/main/api/change.ts +0 -14
- package/src/main/api/game-map-data.ts +0 -26
- package/src/main/api/plaque-type.ts +0 -6
- package/src/main/api/server-group-data.ts +0 -65
- package/src/main/api/vidiot-map-data.ts +0 -18
- package/src/main/api/vidiot-map-point-of-interest-data.ts +0 -30
- package/src/main/changelog.ts +0 -20
- package/src/main/db/alternates.ts +0 -81
- package/src/main/db/badge-partial.ts +0 -35
- package/src/main/db/game-map.ts +0 -33
- package/src/main/db/server-group.ts +0 -112
- package/src/main/db/vidiot-map-point-of-interest.ts +0 -40
- package/src/main/db/vidiot-map.ts +0 -25
- package/src/main/util.ts +0 -17
- package/src/test/api/badge-partial-data.fixture.ts +0 -17
- package/src/test/api/badge-partial-type.test.ts +0 -31
- package/src/test/api/game-map-data.fixture.ts +0 -10
- package/src/test/api/plaque-type.test.ts +0 -31
- package/src/test/api/server-group-data.fixture.ts +0 -23
- package/src/test/api/server-group-data.test.ts +0 -15
- package/src/test/api/vidiot-map-point-of-interest.fixture.ts +0 -10
- package/src/test/api/vidiot-map.fixture.ts +0 -9
- package/src/test/changelog.test.ts +0 -36
- package/src/test/db/alternates.test.ts +0 -223
- package/src/test/db/server-group.test.ts +0 -124
- package/src/test/index.test.ts +0 -10
- package/src/test/util.test.ts +0 -39
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Zone } from '../../main'
|
|
2
|
+
import { zoneDataFixture } from '../api/zone-data.fixture'
|
|
3
|
+
|
|
4
|
+
describe(Zone.name, () => {
|
|
5
|
+
describe('Constructor', () => {
|
|
6
|
+
test(`should accept the test fixture`, () => {
|
|
7
|
+
new Zone(zoneDataFixture.create())
|
|
8
|
+
})
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
describe('key', () => {
|
|
12
|
+
test(`should be set from the data`, () => {
|
|
13
|
+
const zone = new Zone(zoneDataFixture.create({ key: 'foo' }))
|
|
14
|
+
expect(zone.key).toEqual('foo')
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('name', () => {
|
|
19
|
+
test(`should be set from the data`, () => {
|
|
20
|
+
const zone = new Zone(zoneDataFixture.create({ name: 'foo' }))
|
|
21
|
+
expect(zone.name).toEqual('foo')
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('type', () => {
|
|
26
|
+
test(`should be set from the data`, () => {
|
|
27
|
+
const zone = new Zone(zoneDataFixture.create({ type: 'city' }))
|
|
28
|
+
expect(zone.type).toEqual('city')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('morality', () => {
|
|
33
|
+
test(`should be set from the data`, () => {
|
|
34
|
+
const zone = new Zone(zoneDataFixture.create({ morality: ['hero'] }))
|
|
35
|
+
expect(zone.morality?.hero).toBeTruthy()
|
|
36
|
+
expect(zone.morality?.vigilante).toBeFalsy()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test(`should be optional`, () => {
|
|
40
|
+
const zone = new Zone(zoneDataFixture.omit('morality').create())
|
|
41
|
+
expect(zone.morality?.all).toBeTruthy()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('levelRange', () => {
|
|
46
|
+
test(`should be set from the data`, () => {
|
|
47
|
+
const zone = new Zone(zoneDataFixture.create({ levelRange: [10] }))
|
|
48
|
+
expect(zone.levelRange?.min).toEqual(10)
|
|
49
|
+
expect(zone.levelRange?.max).toBeUndefined()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test(`should be optional`, () => {
|
|
53
|
+
const zone = new Zone(zoneDataFixture.omit('levelRange').create())
|
|
54
|
+
expect(zone.levelRange).toBeUndefined()
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('notes', () => {
|
|
59
|
+
test(`should be set from the data`, () => {
|
|
60
|
+
const zone = new Zone(zoneDataFixture.create({ notes: 'foo' }))
|
|
61
|
+
expect(zone.notes).toEqual('foo')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test(`should be optional`, () => {
|
|
65
|
+
const zone = new Zone(zoneDataFixture.omit('notes').create())
|
|
66
|
+
expect(zone.notes).toBeUndefined()
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe('links', () => {
|
|
71
|
+
test(`should be set from the data`, () => {
|
|
72
|
+
const zone = new Zone(zoneDataFixture.create({ links: [{ title: 'foo', href: 'bar' }] }))
|
|
73
|
+
expect(zone.links).toStrictEqual([{ title: 'foo', href: 'bar' }])
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test(`should be optional`, () => {
|
|
77
|
+
const zone = new Zone(zoneDataFixture.omit('links').create())
|
|
78
|
+
expect(zone.links).toHaveLength(0)
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BundleData } from '../main'
|
|
2
|
+
import { TEST_BADGE } from './api/badge-data.test'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* If you change this test, update the example in the README as well
|
|
6
|
+
*/
|
|
7
|
+
export const MyBundle: BundleData = {
|
|
8
|
+
header: { name: 'My Content Bundle', version: '1.0.0', lastUpdateTime: '2025-04-21T00:00:00Z' },
|
|
9
|
+
badges: [TEST_BADGE],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe('BundleData', () => {
|
|
13
|
+
test('should be a usable interface', () => {
|
|
14
|
+
expect(MyBundle).not.toBeUndefined()
|
|
15
|
+
})
|
|
16
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { coalesceToArray } from '../../main/util/coalesce-to-array'
|
|
2
|
+
|
|
3
|
+
describe(coalesceToArray.name, () => {
|
|
4
|
+
test('should return an array unmodified', () => {
|
|
5
|
+
expect(coalesceToArray(['a', 'b'])).toStrictEqual(['a', 'b'])
|
|
6
|
+
expect(coalesceToArray([1, 2])).toStrictEqual([1, 2])
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('should return a single value as a single-value array', () => {
|
|
10
|
+
expect(coalesceToArray('a')).toStrictEqual(['a'])
|
|
11
|
+
expect(coalesceToArray(1)).toStrictEqual([1])
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('should return undefined value as undefined', () => {
|
|
15
|
+
expect(coalesceToArray()).toBeUndefined()
|
|
16
|
+
})
|
|
17
|
+
})
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Badge, badgeLink, badgeUri, Contact, contactLink, contactUri, Mission, missionLink, missionUri, Zone, zoneLink, zoneUri } from '../../main'
|
|
2
|
+
import { badgeDataFixture } from '../api/badge-data.fixture'
|
|
3
|
+
import { zoneDataFixture } from '../api/zone-data.fixture'
|
|
4
|
+
import { contactDataFixture } from '../api/contact-data.fixture'
|
|
5
|
+
import { missionDataFixture } from '../api/mission-data.fixture'
|
|
6
|
+
|
|
7
|
+
describe(badgeUri.name, () => {
|
|
8
|
+
test('should return the expected pattern', () => {
|
|
9
|
+
expect(badgeUri('foo')).toBe('badge://foo')
|
|
10
|
+
expect(badgeUri('bar')).toBe('badge://bar')
|
|
11
|
+
expect(badgeUri('foo-bar')).toBe('badge://foo-bar')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('should accept a Badge object', () => {
|
|
15
|
+
const badge = new Badge(badgeDataFixture.create({ key: 'foo' }))
|
|
16
|
+
expect(badgeUri(badge)).toBe('badge://foo')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('should accept a BadgeData object', () => {
|
|
20
|
+
const badge = badgeDataFixture.create({ key: 'foo' })
|
|
21
|
+
expect(badgeUri(badge)).toBe('badge://foo')
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe(badgeLink.name, () => {
|
|
26
|
+
test('should return the expected pattern', () => {
|
|
27
|
+
expect(badgeLink('foo')).toBe('[foo](badge://foo)')
|
|
28
|
+
expect(badgeLink('bar')).toBe('[bar](badge://bar)')
|
|
29
|
+
expect(badgeLink('foo-bar')).toBe('[foo-bar](badge://foo-bar)')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('should accept a Badge object', () => {
|
|
33
|
+
const badge = new Badge(badgeDataFixture.create({ key: 'foo' }))
|
|
34
|
+
expect(badgeLink(badge)).toBe('[foo](badge://foo)')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('should accept a BadgeData object', () => {
|
|
38
|
+
const badge = badgeDataFixture.create({ key: 'foo' })
|
|
39
|
+
expect(badgeLink(badge)).toBe('[foo](badge://foo)')
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe(contactUri.name, () => {
|
|
44
|
+
test('should return the expected pattern', () => {
|
|
45
|
+
expect(contactUri('foo')).toBe('contact://foo')
|
|
46
|
+
expect(contactUri('bar')).toBe('contact://bar')
|
|
47
|
+
expect(contactUri('foo-bar')).toBe('contact://foo-bar')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('should accept a Contact object', () => {
|
|
51
|
+
const contact = new Contact(contactDataFixture.create({ key: 'foo' }))
|
|
52
|
+
expect(contactUri(contact)).toBe('contact://foo')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('should accept a ContactData object', () => {
|
|
56
|
+
const contact = contactDataFixture.create({ key: 'foo' })
|
|
57
|
+
expect(contactUri(contact)).toBe('contact://foo')
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe(contactLink.name, () => {
|
|
62
|
+
test('should return the expected pattern', () => {
|
|
63
|
+
expect(contactLink('foo')).toBe('[foo](contact://foo)')
|
|
64
|
+
expect(contactLink('bar')).toBe('[bar](contact://bar)')
|
|
65
|
+
expect(contactLink('foo-bar')).toBe('[foo-bar](contact://foo-bar)')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('should accept a Contact object', () => {
|
|
69
|
+
const contact = new Contact(contactDataFixture.create({ key: 'foo' }))
|
|
70
|
+
expect(contactLink(contact)).toBe('[foo](contact://foo)')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('should accept a ContactData object', () => {
|
|
74
|
+
const contact = contactDataFixture.create({ key: 'foo' })
|
|
75
|
+
expect(contactLink(contact)).toBe('[foo](contact://foo)')
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
describe(missionUri.name, () => {
|
|
80
|
+
test('should return the expected pattern', () => {
|
|
81
|
+
expect(missionUri('foo')).toBe('mission://foo')
|
|
82
|
+
expect(missionUri('bar')).toBe('mission://bar')
|
|
83
|
+
expect(missionUri('foo-bar')).toBe('mission://foo-bar')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('should accept a Mission object', () => {
|
|
87
|
+
const mission = new Mission(missionDataFixture.create({ key: 'foo' }))
|
|
88
|
+
expect(missionUri(mission)).toBe('mission://foo')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('should accept a MissionData object', () => {
|
|
92
|
+
const mission = missionDataFixture.create({ key: 'foo' })
|
|
93
|
+
expect(missionUri(mission)).toBe('mission://foo')
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
describe(missionLink.name, () => {
|
|
98
|
+
test('should return the expected pattern', () => {
|
|
99
|
+
expect(missionLink('foo')).toBe('[foo](mission://foo)')
|
|
100
|
+
expect(missionLink('bar')).toBe('[bar](mission://bar)')
|
|
101
|
+
expect(missionLink('foo-bar')).toBe('[foo-bar](mission://foo-bar)')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('should accept a Mission object', () => {
|
|
105
|
+
const mission = new Mission(missionDataFixture.create({ key: 'foo' }))
|
|
106
|
+
expect(missionLink(mission)).toBe('[foo](mission://foo)')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('should accept a MissionData object', () => {
|
|
110
|
+
const mission = missionDataFixture.create({ key: 'foo' })
|
|
111
|
+
expect(missionLink(mission)).toBe('[foo](mission://foo)')
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
describe(zoneUri.name, () => {
|
|
116
|
+
test('should return the expected pattern', () => {
|
|
117
|
+
expect(zoneUri('foo')).toBe('zone://foo')
|
|
118
|
+
expect(zoneUri('bar')).toBe('zone://bar')
|
|
119
|
+
expect(zoneUri('foo-bar')).toBe('zone://foo-bar')
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('should accept a Zone object', () => {
|
|
123
|
+
const zone = new Zone(zoneDataFixture.create({ key: 'foo' }))
|
|
124
|
+
expect(zoneUri(zone)).toBe('zone://foo')
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('should accept a ZoneData object', () => {
|
|
128
|
+
const zone = zoneDataFixture.create({ key: 'foo' })
|
|
129
|
+
expect(zoneUri(zone)).toBe('zone://foo')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
describe(zoneLink.name, () => {
|
|
134
|
+
test('should return the expected pattern', () => {
|
|
135
|
+
expect(zoneLink('foo')).toBe('[foo](zone://foo)')
|
|
136
|
+
expect(zoneLink('bar')).toBe('[bar](zone://bar)')
|
|
137
|
+
expect(zoneLink('foo-bar')).toBe('[foo-bar](zone://foo-bar)')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
test('should accept a Zone object', () => {
|
|
141
|
+
const zone = new Zone(zoneDataFixture.create({ key: 'foo' }))
|
|
142
|
+
expect(zoneLink(zone)).toBe('[foo](zone://foo)')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('should accept a ZoneData object', () => {
|
|
146
|
+
const zone = zoneDataFixture.create({ key: 'foo' })
|
|
147
|
+
expect(zoneLink(zone)).toBe('[foo](zone://foo)')
|
|
148
|
+
})
|
|
149
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { toDate } from '../../main/util/to-date'
|
|
2
|
+
|
|
3
|
+
describe(toDate.name, () => {
|
|
4
|
+
test('should return a valid date', () => {
|
|
5
|
+
expect(toDate('2025-02-01')).toStrictEqual(new Date('2025-02-01'))
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('should return a valid time', () => {
|
|
9
|
+
expect(toDate('2025-04-21T02:57:52.402Z')).toStrictEqual(new Date('2025-04-21T02:57:52.402Z'))
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('should throw on invalid ISO string', () => {
|
|
13
|
+
expect(() => toDate('foo')).toThrow('Invalid date')
|
|
14
|
+
})
|
|
15
|
+
})
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Sex } from './sex'
|
|
2
|
-
import { Alignment } from './alignment'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Some badge values differ based on the alignment or sex of the character.
|
|
6
|
-
*/
|
|
7
|
-
export interface AlternateData<V> {
|
|
8
|
-
/**
|
|
9
|
-
* The character alignment this alternate applies to.
|
|
10
|
-
*/
|
|
11
|
-
readonly alignment?: Alignment | string
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The character sex this alternate applies to.
|
|
15
|
-
*/
|
|
16
|
-
readonly sex?: Sex | string
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The value for this combination.
|
|
20
|
-
*/
|
|
21
|
-
readonly value: V
|
|
22
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { EnhancementCategory } from './enhancement-category'
|
|
2
|
-
import { BadgePartialType } from './badge-partial-type'
|
|
3
|
-
import { PlaqueType } from './plaque-type'
|
|
4
|
-
|
|
5
|
-
export interface BadgePartialData {
|
|
6
|
-
/**
|
|
7
|
-
* Key.
|
|
8
|
-
*/
|
|
9
|
-
readonly key: string
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Type of partial.
|
|
13
|
-
*/
|
|
14
|
-
readonly type: BadgePartialType | string
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Map the partial is located on.
|
|
18
|
-
*/
|
|
19
|
-
readonly mapKey?: string
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* /loc coordinates.
|
|
23
|
-
*/
|
|
24
|
-
readonly loc?: number[]
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Is it a wall plaque or a physical monument?
|
|
28
|
-
*/
|
|
29
|
-
readonly plaqueType?: PlaqueType | string
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Plaque inscription.
|
|
33
|
-
*/
|
|
34
|
-
readonly inscription?: string
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* The number or letter the partial appears as on Vidiot Maps.
|
|
38
|
-
*/
|
|
39
|
-
readonly vidiotMapKey?: string
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* The badge required for this partial.
|
|
43
|
-
*/
|
|
44
|
-
readonly badgeKey?: string
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Level of the invention required.
|
|
48
|
-
*/
|
|
49
|
-
readonly inventionLevel?: number
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* The types of enhancements required to be crafted.
|
|
53
|
-
*/
|
|
54
|
-
readonly inventionTypes?: (EnhancementCategory | string)[]
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Number of invention crafts required.
|
|
58
|
-
*/
|
|
59
|
-
readonly inventionCount?: number
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Any additional notes.
|
|
63
|
-
*/
|
|
64
|
-
readonly notes?: string
|
|
65
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export const BADGE_PARTIAL_TYPE = [
|
|
2
|
-
'PLAQUE',
|
|
3
|
-
'BADGE',
|
|
4
|
-
'INVENTION',
|
|
5
|
-
'INVENTION_PLUS_ONE', // Some invention badges require you to build x of two different invention levels, 'plus one of either level'.
|
|
6
|
-
] as const
|
|
7
|
-
|
|
8
|
-
export type BadgePartialType = typeof BADGE_PARTIAL_TYPE[number]
|
package/src/main/api/change.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface Change {
|
|
2
|
-
/**
|
|
3
|
-
* The version number in {@link http://semver.org|semver} format.
|
|
4
|
-
*/
|
|
5
|
-
version: string
|
|
6
|
-
/**
|
|
7
|
-
* Date of the change.
|
|
8
|
-
*/
|
|
9
|
-
date: Date
|
|
10
|
-
/**
|
|
11
|
-
* Description of the change in {@link https://www.markdownguide.org/|Markdown} format.
|
|
12
|
-
*/
|
|
13
|
-
description: string
|
|
14
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Link } from './link'
|
|
2
|
-
import { VidiotMapData } from './vidiot-map-data'
|
|
3
|
-
|
|
4
|
-
export interface GameMapData {
|
|
5
|
-
/**
|
|
6
|
-
* Unique key used to reference this badge.
|
|
7
|
-
*
|
|
8
|
-
* Keys can only contain lowercase letters, numbers and hyphens (`-`).
|
|
9
|
-
*/
|
|
10
|
-
readonly key: string
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The name of the map as it appears in-game.
|
|
14
|
-
*/
|
|
15
|
-
readonly name: string
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* List of external links for this Map. Wiki, forums, etc.
|
|
19
|
-
*/
|
|
20
|
-
readonly links?: Link[]
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* List of Vidiot Map assets for this map.
|
|
24
|
-
*/
|
|
25
|
-
readonly vidiotMaps?: VidiotMapData[]
|
|
26
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { ArchetypeData } from './archetype-data'
|
|
2
|
-
import { GameMapData } from './game-map-data'
|
|
3
|
-
import { BadgeData } from './badge-data'
|
|
4
|
-
import { Change } from './change'
|
|
5
|
-
import { Link } from './link'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* A server group is a group or company that hosts a set of game servers, such as Homecoming (https://forums.homecomingservers.com/).
|
|
9
|
-
*/
|
|
10
|
-
export interface ServerGroupData {
|
|
11
|
-
/**
|
|
12
|
-
* Unique key used to reference this server group.
|
|
13
|
-
*
|
|
14
|
-
* Keys can only contain lowercase letters, numbers and hyphens (`-`).
|
|
15
|
-
*/
|
|
16
|
-
readonly key: string
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Name of the server group.
|
|
20
|
-
*/
|
|
21
|
-
readonly name: string
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Description of the server group.
|
|
25
|
-
*
|
|
26
|
-
* Supports {@link https://www.markdownguide.org/|Markdown} format.
|
|
27
|
-
*/
|
|
28
|
-
readonly description?: string
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Repository where the db content package is maintained.
|
|
32
|
-
*/
|
|
33
|
-
readonly repository?: string
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* List of external links for this Badge. Wiki, forums, etc.
|
|
37
|
-
*/
|
|
38
|
-
readonly links?: Link[]
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* List of the game server names in this server group.
|
|
42
|
-
* Torchbearer, Excelsior, etc.
|
|
43
|
-
*/
|
|
44
|
-
readonly servers?: string[]
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* List of archetypes available in this server group.
|
|
48
|
-
*/
|
|
49
|
-
readonly archetypes?: ArchetypeData[]
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* List of game maps supported by this server group.
|
|
53
|
-
*/
|
|
54
|
-
readonly maps?: GameMapData[]
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* List of badges available on this server group.
|
|
58
|
-
*/
|
|
59
|
-
readonly badges?: BadgeData[]
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Change log for this data package.
|
|
63
|
-
*/
|
|
64
|
-
readonly changelog?: Change[]
|
|
65
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { VidiotMapPointOfInterestData } from './vidiot-map-point-of-interest-data'
|
|
2
|
-
|
|
3
|
-
export interface VidiotMapData {
|
|
4
|
-
/**
|
|
5
|
-
* URL of the map image.
|
|
6
|
-
*/
|
|
7
|
-
readonly imageUrl: string
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Name to display for the Vidiot map.
|
|
11
|
-
*/
|
|
12
|
-
readonly name?: string
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* List of Points of Interest labelled on the image.
|
|
16
|
-
*/
|
|
17
|
-
readonly pointsOfInterest?: VidiotMapPointOfInterestData[]
|
|
18
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export interface VidiotMapPointOfInterestData {
|
|
2
|
-
/**
|
|
3
|
-
* The pixel-space position of the PoI on the map graphic.
|
|
4
|
-
*
|
|
5
|
-
* Screen-space, pixels from top-left `[0, 0]`.
|
|
6
|
-
*/
|
|
7
|
-
readonly pos?: [number, number]
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Freeform notes about the PoI.
|
|
11
|
-
*
|
|
12
|
-
* Supports {@link https://www.markdownguide.org/|Markdown} format.
|
|
13
|
-
*/
|
|
14
|
-
readonly notes?: string
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* If the POI is a zone transfer, the map it transfers to.
|
|
18
|
-
*/
|
|
19
|
-
readonly mapKey?: string
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* If the POI is a badge, the badge.
|
|
23
|
-
*/
|
|
24
|
-
readonly badgeKey?: string
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* If the POI is a partial for a badge, the partial key.
|
|
28
|
-
*/
|
|
29
|
-
readonly badgePartialKey?: string
|
|
30
|
-
}
|
package/src/main/changelog.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Change } from './api/change'
|
|
2
|
-
|
|
3
|
-
export const CHANGELOG: Change[] = [
|
|
4
|
-
{
|
|
5
|
-
version: '2.0.0',
|
|
6
|
-
date: new Date('2025-03-12'),
|
|
7
|
-
description: ''
|
|
8
|
-
+ '* Replaced redundant interfaces with their concrete equivalents.\n'
|
|
9
|
-
+ '* Replaced enums with extensible union types; Server groups with new badge types, enhancement types, etc. can now extend them locally.\n'
|
|
10
|
-
+ '* Removed the `serverGroup` property from entities to simplify the object tree; Server group context will need to be managed separately.\n'
|
|
11
|
-
+ '* Standardized pluralization of some field names (name, icon).\n'
|
|
12
|
-
+ '* Combined `settitle` ids into a single tuple field.\n'
|
|
13
|
-
+ '* Change from GNU to The Unlicense.\n'
|
|
14
|
-
+ '* Removed dependency on lodash. There are now no third-party runtime dependencies.\n'
|
|
15
|
-
+ '* Moved from webpack to rollup for packaging.\n'
|
|
16
|
-
+ '* Add eslint for linting.\n'
|
|
17
|
-
+ '* Add jest for unit tests.\n'
|
|
18
|
-
+ '* Added GitHub Actions for CI.\n',
|
|
19
|
-
},
|
|
20
|
-
]
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { AlternateData } from '../api/alternate-data'
|
|
2
|
-
import { Sex } from '../api/sex'
|
|
3
|
-
import { Alignment } from '../api/alignment'
|
|
4
|
-
|
|
5
|
-
const ALIGNMENT_SORT: Record<string, number> = { H: 2, V: 1, P: 0 }
|
|
6
|
-
const SEX_SORT: Record<string, number> = { M: 1, F: 0 }
|
|
7
|
-
|
|
8
|
-
export class Alternates<T> {
|
|
9
|
-
readonly #sortedValues: AlternateData<T>[] = []
|
|
10
|
-
|
|
11
|
-
constructor(values: AlternateData<T>[]) {
|
|
12
|
-
this.#sortedValues = values.sort()
|
|
13
|
-
this.#sortedValues.sort((a, b) => this.#compareAlternates(a, b))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
getValue(alignment?: Alignment | string, sex?: Sex | string): T | undefined {
|
|
17
|
-
for (let index = this.#sortedValues.length; index--;) {
|
|
18
|
-
const entry = this.#sortedValues[index]
|
|
19
|
-
if ((entry.alignment === undefined || entry.alignment === alignment)
|
|
20
|
-
&& (entry.sex === undefined || entry.sex === sex)
|
|
21
|
-
) return entry.value
|
|
22
|
-
}
|
|
23
|
-
return undefined
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get the default value for this list of alternates, the value with the highest priority and lowest specificity.
|
|
28
|
-
*/
|
|
29
|
-
get default(): T | undefined {
|
|
30
|
-
return this.#sortedValues[0]?.value
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get the list of alternates sorted in canonical order (alignment then sex, low to high specificity).
|
|
35
|
-
*/
|
|
36
|
-
get canonical(): AlternateData<T>[] {
|
|
37
|
-
return this.#sortedValues
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
#compareAlternates(a: AlternateData<T>, b: AlternateData<T>): number {
|
|
41
|
-
const aSpecificity = (a.alignment ? 2 : 0) + (a.sex ? 1 : 0)
|
|
42
|
-
const bSpecificity = (b.alignment ? 2 : 0) + (b.sex ? 1 : 0)
|
|
43
|
-
if (aSpecificity !== bSpecificity) return aSpecificity - bSpecificity // Order first by least-specific
|
|
44
|
-
|
|
45
|
-
const alignmentComparison = this.#compareAlignment(a.alignment, b.alignment) // Next by alignment
|
|
46
|
-
if (alignmentComparison !== 0) return alignmentComparison
|
|
47
|
-
|
|
48
|
-
const sexComparison = this.#compareSex(a.sex, b.sex) // Last by sex
|
|
49
|
-
if (sexComparison !== 0) return sexComparison
|
|
50
|
-
|
|
51
|
-
return String(a.value).localeCompare(String(b.value))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
#compareAlignment(a: Alignment | string | undefined, b: Alignment | string | undefined): number {
|
|
55
|
-
if (a === b) return 0
|
|
56
|
-
if (a === undefined && b !== undefined) return -1
|
|
57
|
-
if (b === undefined && a !== undefined) return 1
|
|
58
|
-
|
|
59
|
-
const aSort = a === undefined ? -1 : ALIGNMENT_SORT[a] ?? -1 // Unknown values get -1 priority
|
|
60
|
-
const bSort = b === undefined ? -1 : ALIGNMENT_SORT[b] ?? -1
|
|
61
|
-
|
|
62
|
-
if (aSort !== bSort) return bSort - aSort
|
|
63
|
-
|
|
64
|
-
// Unknown values (not in ALIGNMENT_SORT) are sorted alphabetically
|
|
65
|
-
return a?.localeCompare(b ?? '') ?? 0
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
#compareSex(a?: Sex | string | undefined, b?: Sex | string | undefined): number {
|
|
69
|
-
if (a === b) return 0
|
|
70
|
-
if (a === undefined && b !== undefined) return -1
|
|
71
|
-
if (b === undefined && a !== undefined) return 1
|
|
72
|
-
|
|
73
|
-
const aSort = SEX_SORT[a ?? -1] ?? -1 // Unknown values get -1 priority
|
|
74
|
-
const bSort = SEX_SORT[b ?? -1] ?? -1
|
|
75
|
-
|
|
76
|
-
if (aSort !== bSort) return bSort - aSort
|
|
77
|
-
|
|
78
|
-
// Unknown values (not in SEX_SORT) are sorted alphabetically
|
|
79
|
-
return a?.localeCompare(b ?? '') ?? 0
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { BadgePartialData } from '../api/badge-partial-data'
|
|
2
|
-
import { PlaqueType } from '../api/plaque-type'
|
|
3
|
-
import { BadgePartialType } from '../api/badge-partial-type'
|
|
4
|
-
import { EnhancementCategory } from '../api/enhancement-category'
|
|
5
|
-
import { Key } from './key'
|
|
6
|
-
|
|
7
|
-
export class BadgePartial {
|
|
8
|
-
readonly key: string
|
|
9
|
-
readonly type: BadgePartialType | string
|
|
10
|
-
readonly mapKey?: string
|
|
11
|
-
readonly loc?: number[]
|
|
12
|
-
readonly plaqueType?: PlaqueType | string
|
|
13
|
-
readonly inscription?: string
|
|
14
|
-
readonly vidiotMapKey?: string
|
|
15
|
-
readonly badgeKey?: string
|
|
16
|
-
readonly inventionLevel?: number
|
|
17
|
-
readonly inventionTypes?: (EnhancementCategory | string)[]
|
|
18
|
-
readonly inventionCount?: number
|
|
19
|
-
readonly notes?: string
|
|
20
|
-
|
|
21
|
-
constructor(data: BadgePartialData) {
|
|
22
|
-
this.key = new Key(data.key).value
|
|
23
|
-
this.type = data.type
|
|
24
|
-
this.mapKey = data.mapKey
|
|
25
|
-
this.loc = data.loc
|
|
26
|
-
this.plaqueType = data.plaqueType
|
|
27
|
-
this.inscription = data.inscription
|
|
28
|
-
this.vidiotMapKey = data.vidiotMapKey
|
|
29
|
-
this.badgeKey = data.badgeKey
|
|
30
|
-
this.inventionLevel = data.inventionLevel
|
|
31
|
-
this.inventionTypes = data.inventionTypes
|
|
32
|
-
this.inventionCount = data.inventionCount
|
|
33
|
-
this.notes = data.notes
|
|
34
|
-
}
|
|
35
|
-
}
|