sekai-calculator 0.0.8 → 0.1.0

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/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # sekai-calculator
2
2
  Project SEKAI Calculator for deck power, live score, event point and more.
3
3
 
4
- Both ECMAScript Module `index.mjs` and CommonJS `index.cjs` are provided with types `index.d.ts` attached.
4
+ This project is fully made up in TypeScript, while reducing `any` as possible.
5
+
6
+ Both ECMAScript Module `index.mjs` and CommonJS `index.cjs` are provided with types `index.d.ts` for TypeScript.
5
7
 
6
8
  ## Quick Start
7
9
  W.I.P.
package/dist/index.cjs CHANGED
@@ -6,11 +6,221 @@ function findOrThrow(arr, p) {
6
6
  throw new Error('object not found');
7
7
  return result;
8
8
  }
9
+ function getOrThrow(map, key) {
10
+ const value = map.get(key);
11
+ if (value === undefined)
12
+ throw new Error('key not found');
13
+ return value;
14
+ }
15
+ function getOrDefault(map, key, defaultValue) {
16
+ const value = map.get(key);
17
+ if (value === undefined)
18
+ return defaultValue;
19
+ return value;
20
+ }
21
+ function computeWithDefault(map, key, defaultValue, action) {
22
+ map.set(key, action(getOrDefault(map, key, defaultValue)));
23
+ }
24
+ function duplicateObj(obj, times) {
25
+ const ret = [];
26
+ for (let i = 0; i < times; ++i)
27
+ ret.push(obj);
28
+ return ret;
29
+ }
30
+ function mapOrUndefined(arr, fun) {
31
+ if (arr === undefined)
32
+ return undefined;
33
+ return arr.map(fun);
34
+ }
35
+
36
+ class CardPowerCalculator {
37
+ dataProvider;
38
+ constructor(dataProvider) {
39
+ this.dataProvider = dataProvider;
40
+ }
41
+ async getCardPower(userCard, card, cardUnits, userAreaItemLevels) {
42
+ const ret = new CardDetailMap();
43
+ const basePower = await this.getCardBasePowers(userCard, card);
44
+ const characterBonus = await this.getCharacterBonusPower(basePower, card.characterId);
45
+ for (const unit of cardUnits) {
46
+ ret.set(unit, 5, 5, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, true, true));
47
+ ret.set(unit, 5, 1, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, true, false));
48
+ ret.set(unit, 1, 5, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, false, true));
49
+ ret.set(unit, 1, 1, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, false, false));
50
+ }
51
+ return ret;
52
+ }
53
+ async getPower(card, basePower, characterBonus, userAreaItemLevels, unit, sameUnit, sameAttr) {
54
+ return basePower.reduce((v, it) => v + it, 0) + characterBonus + await this.getAreaItemBonusPower(userAreaItemLevels, basePower, card.characterId, unit, sameUnit, card.attr, sameAttr);
55
+ }
56
+ async getCardBasePowers(userCard, card) {
57
+ const cardEpisodes = await this.dataProvider.getMasterData('cardEpisodes');
58
+ const masterLessons = await this.dataProvider.getMasterData('masterLessons');
59
+ const ret = [0, 0, 0];
60
+ const cardParameters = card.cardParameters.filter(it => it.cardLevel === userCard.level);
61
+ const params = ['param1', 'param2', 'param3'];
62
+ params.forEach((param, i) => {
63
+ ret[i] = findOrThrow(cardParameters, it => it.cardParameterType === param).power;
64
+ });
65
+ if (userCard.specialTrainingStatus === 'done') {
66
+ ret[0] += card.specialTrainingPower1BonusFixed;
67
+ ret[1] += card.specialTrainingPower2BonusFixed;
68
+ ret[2] += card.specialTrainingPower3BonusFixed;
69
+ }
70
+ const episodes = userCard.episodes.filter(it => it.scenarioStatus === 'already_read')
71
+ .map(it => findOrThrow(cardEpisodes, e => e.id === it.cardEpisodeId));
72
+ for (const episode of episodes) {
73
+ ret[0] += episode.power1BonusFixed;
74
+ ret[1] += episode.power2BonusFixed;
75
+ ret[2] += episode.power3BonusFixed;
76
+ }
77
+ const usedMasterLessons = masterLessons
78
+ .filter((it) => it.cardRarityType === card.cardRarityType && it.masterRank <= userCard.masterRank);
79
+ for (const masterLesson of usedMasterLessons) {
80
+ ret[0] += masterLesson.power1BonusFixed;
81
+ ret[1] += masterLesson.power2BonusFixed;
82
+ ret[2] += masterLesson.power3BonusFixed;
83
+ }
84
+ return ret;
85
+ }
86
+ async getAreaItemBonusPower(userAreaItemLevels, basePower, characterId, unit, sameUnit, attr, sameAttr) {
87
+ const usedAreaItems = userAreaItemLevels.filter(it => (it.targetUnit === 'any' || it.targetUnit === unit) &&
88
+ (it.targetCardAttr === 'any' || it.targetCardAttr === attr) &&
89
+ (it.targetGameCharacterId === undefined || it.targetGameCharacterId === characterId));
90
+ const areaItemBonus = [0, 0, 0];
91
+ for (const areaItem of usedAreaItems) {
92
+ const allMatch = (areaItem.targetUnit !== 'any' && sameUnit) || (areaItem.targetCardAttr !== 'any' && sameAttr);
93
+ areaItemBonus[0] += allMatch ? areaItem.power1AllMatchBonusRate : areaItem.power1BonusRate;
94
+ areaItemBonus[1] += allMatch ? areaItem.power2AllMatchBonusRate : areaItem.power2BonusRate;
95
+ areaItemBonus[2] += allMatch ? areaItem.power3AllMatchBonusRate : areaItem.power3BonusRate;
96
+ }
97
+ return basePower.reduce((v, it, i) => v + Math.floor(it * areaItemBonus[i] / 100), 0);
98
+ }
99
+ async getCharacterBonusPower(basePower, characterId) {
100
+ const characterRanks = await this.dataProvider.getMasterData('characterRanks');
101
+ const userCharacters = await this.dataProvider.getUserData('userCharacters');
102
+ const userCharacter = findOrThrow(userCharacters, it => it.characterId === characterId);
103
+ const characterRank = findOrThrow(characterRanks, it => it.characterId === userCharacter.characterId && it.characterRank === userCharacter.characterRank);
104
+ const rates = [characterRank.power1BonusRate, characterRank.power2BonusRate, characterRank.power3BonusRate];
105
+ return rates.reduce((v, it, i) => v + Math.floor(basePower[i] * it / 100), 0);
106
+ }
107
+ }
108
+
109
+ class CardSkillCalculator {
110
+ dataProvider;
111
+ constructor(dataProvider) {
112
+ this.dataProvider = dataProvider;
113
+ }
114
+ async getCardSkill(userCard, card) {
115
+ const scoreUpMap = new CardDetailMap();
116
+ const detail = await this.getSkillDetail(userCard, card);
117
+ if (detail.scoreUpEnhance !== undefined) {
118
+ for (let i = 1; i <= 5; ++i) {
119
+ const scoreUp = detail.scoreUp + (i === 5 ? 5 : (i - 1)) * detail.scoreUpEnhance.value;
120
+ scoreUpMap.set(detail.scoreUpEnhance.unit, i, 1, scoreUp);
121
+ }
122
+ }
123
+ scoreUpMap.set('any', 1, 1, detail.scoreUp);
124
+ return { scoreUp: scoreUpMap, lifeRecovery: detail.lifeRecovery };
125
+ }
126
+ async getSkillDetail(userCard, card) {
127
+ const skills = await this.dataProvider.getMasterData('skills');
128
+ const skill = findOrThrow(skills, it => it.id === card.skillId);
129
+ const ret = { scoreUp: 0, lifeRecovery: 0 };
130
+ for (const skillEffect of skill.skillEffects) {
131
+ const skillEffectDetail = findOrThrow(skillEffect.skillEffectDetails, it => it.level === userCard.skillLevel);
132
+ if (skillEffect.skillEffectType === 'score_up' ||
133
+ skillEffect.skillEffectType === 'score_up_condition_life' ||
134
+ skillEffect.skillEffectType === 'score_up_keep') {
135
+ const current = skillEffectDetail.activateEffectValue;
136
+ if (skillEffect.skillEnhance !== undefined) {
137
+ ret.scoreUpEnhance = {
138
+ unit: skillEffect.skillEnhance.skillEnhanceCondition.unit,
139
+ value: skillEffect.skillEnhance.activateEffectValue
140
+ };
141
+ }
142
+ ret.scoreUp = Math.max(ret.scoreUp, current);
143
+ }
144
+ else if (skillEffect.skillEffectType === 'life_recovery') {
145
+ ret.lifeRecovery += skillEffectDetail.activateEffectValue;
146
+ }
147
+ }
148
+ return ret;
149
+ }
150
+ }
151
+
152
+ class CardCalculator {
153
+ dataProvider;
154
+ powerCalculator;
155
+ skillCalculator;
156
+ constructor(dataProvider) {
157
+ this.dataProvider = dataProvider;
158
+ this.powerCalculator = new CardPowerCalculator(dataProvider);
159
+ this.skillCalculator = new CardSkillCalculator(dataProvider);
160
+ }
161
+ async getCardUnits(card) {
162
+ const gameCharacters = await this.dataProvider.getMasterData('gameCharacters');
163
+ const units = [];
164
+ if (card.supportUnit !== 'none')
165
+ units.push(card.supportUnit);
166
+ units.push(findOrThrow(gameCharacters, it => it.id === card.characterId).unit);
167
+ return units;
168
+ }
169
+ async getCardDetail(userCard, userAreaItemLevels) {
170
+ const cards = await this.dataProvider.getMasterData('cards');
171
+ const card = findOrThrow(cards, it => it.id === userCard.cardId);
172
+ const units = await this.getCardUnits(card);
173
+ const skill = await this.skillCalculator.getCardSkill(userCard, card);
174
+ const power = await this.powerCalculator.getCardPower(userCard, card, units, userAreaItemLevels);
175
+ return {
176
+ cardId: card.id,
177
+ units,
178
+ attr: card.attr,
179
+ power,
180
+ scoreSkill: skill.scoreUp,
181
+ lifeSkill: skill.lifeRecovery
182
+ };
183
+ }
184
+ }
185
+ class CardDetailMap {
186
+ min = Number.MAX_SAFE_INTEGER;
187
+ max = Number.MIN_SAFE_INTEGER;
188
+ values = new Map();
189
+ set(unit, unitMember, attrMember, value) {
190
+ this.min = Math.min(this.min, value);
191
+ this.max = Math.max(this.max, value);
192
+ this.values.set(CardDetailMap.getKey(unit, unitMember, attrMember), value);
193
+ }
194
+ get(unit, unitMember, attrMember) {
195
+ const attrMember0 = attrMember === 5 ? 5 : 1;
196
+ let best = this.getInternal(unit, unitMember, attrMember0);
197
+ if (best !== undefined)
198
+ return best;
199
+ best = this.getInternal(unit, unitMember === 5 ? 5 : 1, attrMember0);
200
+ if (best !== undefined)
201
+ return best;
202
+ best = this.getInternal('any', 1, 1);
203
+ if (best !== undefined)
204
+ return best;
205
+ throw new Error('case not found');
206
+ }
207
+ getInternal(unit, unitMember, attrMember) {
208
+ return this.values.get(CardDetailMap.getKey(unit, unitMember, attrMember));
209
+ }
210
+ static getKey(unit, unitMember, attrMember) {
211
+ return `${unit}-${unitMember}-${attrMember}`;
212
+ }
213
+ isCertainlyLessThen(another) {
214
+ return this.max < another.min;
215
+ }
216
+ }
9
217
 
10
218
  class DeckCalculator {
11
219
  dataProvider;
220
+ cardCalculator;
12
221
  constructor(dataProvider) {
13
222
  this.dataProvider = dataProvider;
223
+ this.cardCalculator = new CardCalculator(dataProvider);
14
224
  }
15
225
  async getDeck(deckId) {
16
226
  const userDecks = await this.dataProvider.getUserData('userDecks');
@@ -24,14 +234,49 @@ class DeckCalculator {
24
234
  async getDeckCardsById(deckId) {
25
235
  return await this.getDeckCards(await this.getDeck(deckId));
26
236
  }
237
+ async getHonorBonusPower() {
238
+ const honors = await this.dataProvider.getMasterData('honors');
239
+ const userHonors = await this.dataProvider.getUserData('userHonors');
240
+ return userHonors
241
+ .map(userHonor => {
242
+ const honor = findOrThrow(honors, it => it.id === userHonor.honorId);
243
+ return findOrThrow(honor.levels, it => it.level === userHonor.level);
244
+ })
245
+ .reduce((v, it) => v + it.bonus, 0);
246
+ }
247
+ async getDeckDetailByCards(cardDetails, honorBonus) {
248
+ const map = new Map();
249
+ for (const cardDetail of cardDetails) {
250
+ computeWithDefault(map, cardDetail.attr, 0, it => it + 1);
251
+ cardDetail.units.forEach(key => { computeWithDefault(map, key, 0, it => it + 1); });
252
+ }
253
+ const power = cardDetails.reduce((v, cardDetail) => v + cardDetail.units.reduce((vv, unit) => Math.max(vv, cardDetail.power.get(unit, getOrThrow(map, unit), getOrThrow(map, cardDetail.attr))), 0), 0) + honorBonus;
254
+ const skill = cardDetails.map(cardDetail => {
255
+ const scoreUp = cardDetail.units.reduce((vv, unit) => Math.max(vv, cardDetail.scoreSkill.get(unit, getOrThrow(map, unit), 1)), 0);
256
+ return {
257
+ cardId: cardDetail.cardId,
258
+ scoreUp,
259
+ lifeRecovery: cardDetail.lifeSkill
260
+ };
261
+ });
262
+ return { power, skill };
263
+ }
264
+ async getDeckDetail(deckCards) {
265
+ const areaItemLevels = await this.dataProvider.getMasterData('areaItemLevels');
266
+ const userAreas = await this.dataProvider.getUserData('userAreas');
267
+ const userItemLevels = userAreas.flatMap(it => it.areaItems).map(areaItem => findOrThrow(areaItemLevels, it => it.areaItemId === areaItem.areaItemId && it.level === areaItem.level));
268
+ const cardDetails = await Promise.all(deckCards.map(async (it) => await this.cardCalculator.getCardDetail(it, userItemLevels)));
269
+ return await this.getDeckDetailByCards(cardDetails, await this.getHonorBonusPower());
270
+ }
271
+ async getDeckDetailById(deckId) {
272
+ return await this.getDeckDetail(await this.getDeckCardsById(deckId));
273
+ }
27
274
  }
28
275
 
29
- class EventCalculator {
276
+ class CardEventCalculator {
30
277
  dataProvider;
31
- deckCalculator;
32
278
  constructor(dataProvider) {
33
279
  this.dataProvider = dataProvider;
34
- this.deckCalculator = new DeckCalculator(dataProvider);
35
280
  }
36
281
  async getEventDeckBonus(eventId, card) {
37
282
  const eventDeckBonuses = await this.dataProvider.getMasterData('eventDeckBonuses');
@@ -65,13 +310,100 @@ class EventCalculator {
65
310
  eventBonus += masterRankBonus.bonusRate;
66
311
  return eventBonus;
67
312
  }
313
+ }
314
+
315
+ class EventCalculator {
316
+ dataProvider;
317
+ deckCalculator;
318
+ cardEventCalculator;
319
+ constructor(dataProvider) {
320
+ this.dataProvider = dataProvider;
321
+ this.deckCalculator = new DeckCalculator(dataProvider);
322
+ this.cardEventCalculator = new CardEventCalculator(dataProvider);
323
+ }
68
324
  async getDeckEventBonus(userDeck, eventId) {
69
325
  const deckCards = await this.deckCalculator.getDeckCards(userDeck);
70
- return await deckCards.reduce(async (v, it) => await this.getCardEventBonus(it, eventId) + await v, Promise.resolve(0));
326
+ return await deckCards.reduce(async (v, it) => await v + await this.cardEventCalculator.getCardEventBonus(it, eventId), Promise.resolve(0));
71
327
  }
72
328
  async getDeckEventBonusById(deckId, eventId) {
73
329
  return await this.getDeckEventBonus(await this.deckCalculator.getDeck(deckId), eventId);
74
330
  }
75
331
  }
76
332
 
333
+ class LiveCalculator {
334
+ dataProvider;
335
+ deckCalculator;
336
+ constructor(dataProvider) {
337
+ this.dataProvider = dataProvider;
338
+ this.deckCalculator = new DeckCalculator(dataProvider);
339
+ }
340
+ getBaseScore(musicMeta, liveType) {
341
+ switch (liveType) {
342
+ case exports.LiveType.SOLO:
343
+ return musicMeta.base_score;
344
+ case exports.LiveType.MULTI:
345
+ return musicMeta.base_score + musicMeta.fever_score;
346
+ case exports.LiveType.AUTO:
347
+ return musicMeta.base_score_auto;
348
+ }
349
+ }
350
+ getSkillScore(musicMeta, liveType) {
351
+ switch (liveType) {
352
+ case exports.LiveType.SOLO:
353
+ return musicMeta.skill_score_solo;
354
+ case exports.LiveType.MULTI:
355
+ return musicMeta.skill_score_multi;
356
+ case exports.LiveType.AUTO:
357
+ return musicMeta.skill_score_auto;
358
+ }
359
+ }
360
+ async getLiveDetailByDeck(deckDetail, musicMeta, liveType, skillDetails = undefined, multiPowerSum = 0) {
361
+ const bestSkill = skillDetails === undefined;
362
+ const skills = bestSkill
363
+ ? [...deckDetail.skill, deckDetail.skill[0]].sort((a, b) => a.scoreUp - b.scoreUp)
364
+ : skillDetails;
365
+ const baseRate = this.getBaseScore(musicMeta, liveType);
366
+ const skillRate = bestSkill
367
+ ? [...this.getSkillScore(musicMeta, liveType)].sort((a, b) => a - b)
368
+ : this.getSkillScore(musicMeta, liveType);
369
+ const rate = baseRate + skills.reduce((v, it, i) => v + it.scoreUp * skillRate[i] / 100, 0);
370
+ const life = skills.reduce((v, it) => v + it.lifeRecovery, 0);
371
+ const powerSum = multiPowerSum === 0 ? 5 * deckDetail.power : multiPowerSum;
372
+ const activeBonus = liveType === exports.LiveType.MULTI ? 5 * 0.015 * powerSum : 0;
373
+ return {
374
+ score: Math.floor(rate * deckDetail.power * 4 + activeBonus),
375
+ time: musicMeta.music_time,
376
+ life: Math.min(2000, life + 1000),
377
+ tap: musicMeta.tap_count
378
+ };
379
+ }
380
+ getMultiLiveSkill(deckDetail) {
381
+ const scoreUp = deckDetail.skill.reduce((v, it, i) => v + (i === 0 ? it.scoreUp : (it.scoreUp / 5)), 0);
382
+ const lifeRecovery = deckDetail.skill[0].lifeRecovery;
383
+ return { scoreUp, lifeRecovery };
384
+ }
385
+ async getLiveDetail(deckCards, musicId, musicDiff, liveType, liveSkills = undefined) {
386
+ const musicMetas = await this.dataProvider.getMusicMeta();
387
+ const musicMeta = findOrThrow(musicMetas, it => it.music_id === musicId && it.difficulty === musicDiff);
388
+ const deckDetail = await this.deckCalculator.getDeckDetail(deckCards);
389
+ const skills = liveType === exports.LiveType.MULTI
390
+ ? duplicateObj(this.getMultiLiveSkill(deckDetail), 6)
391
+ : (mapOrUndefined(liveSkills, liveSkill => findOrThrow(deckDetail.skill, it => it.cardId === liveSkill.cardId)));
392
+ return await this.getLiveDetailByDeck(deckDetail, musicMeta, liveType, skills);
393
+ }
394
+ async getLiveDetailById(deckId, musicId, musicDiff, liveType, liveSkills = undefined) {
395
+ return await this.getLiveDetail(await this.deckCalculator.getDeckCardsById(deckId), musicId, musicDiff, liveType, liveSkills);
396
+ }
397
+ }
398
+ exports.LiveType = void 0;
399
+ (function (LiveType) {
400
+ LiveType["SOLO"] = "solo";
401
+ LiveType["MULTI"] = "multi";
402
+ LiveType["AUTO"] = "auto";
403
+ })(exports.LiveType || (exports.LiveType = {}));
404
+
405
+ exports.CardCalculator = CardCalculator;
406
+ exports.CardDetailMap = CardDetailMap;
407
+ exports.DeckCalculator = DeckCalculator;
77
408
  exports.EventCalculator = EventCalculator;
409
+ exports.LiveCalculator = LiveCalculator;
package/dist/index.d.ts CHANGED
@@ -4,18 +4,6 @@ interface DataProvider {
4
4
  getMusicMeta: () => Promise<any>;
5
5
  }
6
6
 
7
- interface UserCard {
8
- cardId: number;
9
- level?: number;
10
- skillLevel?: number;
11
- masterRank: number;
12
- specialTrainingStatus?: string;
13
- episodes?: Array<{
14
- cardEpisodeId: number;
15
- scenarioStatus: string;
16
- }>;
17
- }
18
-
19
7
  interface UserDeck {
20
8
  deckId: number;
21
9
  member1: number;
@@ -28,19 +16,30 @@ interface UserDeck {
28
16
  declare class EventCalculator {
29
17
  private readonly dataProvider;
30
18
  private readonly deckCalculator;
19
+ private readonly cardEventCalculator;
31
20
  constructor(dataProvider: DataProvider);
32
- private getEventDeckBonus;
33
- getCardEventBonus(userCard: UserCard, eventId: number): Promise<number>;
34
21
  getDeckEventBonus(userDeck: UserDeck, eventId: number): Promise<number>;
35
22
  getDeckEventBonusById(deckId: number, eventId: number): Promise<number>;
36
23
  }
37
24
 
25
+ interface UserCard {
26
+ cardId: number;
27
+ level: number;
28
+ skillLevel: number;
29
+ masterRank: number;
30
+ specialTrainingStatus?: string;
31
+ episodes: Array<{
32
+ cardEpisodeId: number;
33
+ scenarioStatus: string;
34
+ }>;
35
+ }
36
+
38
37
  interface AreaItemLevel {
39
38
  areaItemId: number;
40
39
  level: number;
41
40
  targetUnit: string;
42
41
  targetCardAttr: string;
43
- targetGameCharacterId: number;
42
+ targetGameCharacterId?: number;
44
43
  power1BonusRate: number;
45
44
  power1AllMatchBonusRate: number;
46
45
  power2BonusRate: number;
@@ -50,95 +49,96 @@ interface AreaItemLevel {
50
49
  sentence: string;
51
50
  }
52
51
 
53
- interface CommonResource {
54
- resourceId?: number;
55
- resourceType: string;
56
- resourceLevel?: number;
57
- quantity: number;
52
+ declare class CardCalculator {
53
+ private readonly dataProvider;
54
+ private readonly powerCalculator;
55
+ private readonly skillCalculator;
56
+ constructor(dataProvider: DataProvider);
57
+ private getCardUnits;
58
+ getCardDetail(userCard: UserCard, userAreaItemLevels: AreaItemLevel[]): Promise<CardDetail>;
58
59
  }
59
-
60
- interface Card {
61
- id: number;
62
- seq: number;
63
- characterId: number;
64
- cardRarityType: string;
65
- specialTrainingPower1BonusFixed: number;
66
- specialTrainingPower2BonusFixed: number;
67
- specialTrainingPower3BonusFixed: number;
60
+ interface CardDetail {
61
+ cardId: number;
62
+ units: string[];
68
63
  attr: string;
69
- supportUnit: string;
70
- skillId: number;
71
- cardSkillName: string;
72
- prefix: string;
73
- assetbundleName: string;
74
- gachaPhrase: string;
75
- flavorText: string;
76
- releaseAt: number;
77
- cardParameters: Array<{
78
- id: number;
79
- cardId: number;
80
- cardLevel: number;
81
- cardParameterType: string;
82
- power: number;
83
- }>;
84
- specialTrainingCosts: CommonResource[];
85
- masterLessonAchieveResources: {
86
- releaseConditionId: number;
87
- cardId: number;
88
- masterRank: number;
89
- resources: CommonResource[];
90
- };
64
+ power: CardDetailMap;
65
+ scoreSkill: CardDetailMap;
66
+ lifeSkill: number;
67
+ eventBonus?: number;
91
68
  }
92
-
93
- interface EventCard {
94
- id: number;
95
- cardId: number;
96
- eventId: number;
97
- bonusRate: number;
69
+ declare class CardDetailMap {
70
+ min: number;
71
+ max: number;
72
+ values: Map<string, number>;
73
+ set(unit: string, unitMember: number, attrMember: number, value: number): void;
74
+ get(unit: string, unitMember: number, attrMember: number): number;
75
+ private getInternal;
76
+ static getKey(unit: string, unitMember: number, attrMember: number): string;
77
+ isCertainlyLessThen(another: CardDetailMap): boolean;
98
78
  }
99
79
 
100
- interface EventDeckBonus {
101
- id: number;
102
- eventId: number;
103
- gameCharacterUnitId?: number;
104
- cardAttr?: string;
105
- bonusRate: number;
80
+ declare class DeckCalculator {
81
+ private readonly dataProvider;
82
+ private readonly cardCalculator;
83
+ constructor(dataProvider: DataProvider);
84
+ getDeck(deckId: number): Promise<UserDeck>;
85
+ getDeckCards(userDeck: UserDeck): Promise<UserCard[]>;
86
+ getDeckCardsById(deckId: number): Promise<UserCard[]>;
87
+ private getHonorBonusPower;
88
+ getDeckDetailByCards(cardDetails: CardDetail[], honorBonus: number): Promise<DeckDetail>;
89
+ getDeckDetail(deckCards: UserCard[]): Promise<DeckDetail>;
90
+ getDeckDetailById(deckId: number): Promise<DeckDetail>;
106
91
  }
107
-
108
- interface EventRarityBonusRate {
109
- id: number;
110
- cardRarityType: string;
111
- masterRank: number;
112
- bonusRate: number;
92
+ interface DeckDetail {
93
+ power: number;
94
+ skill: SkillDetail[];
113
95
  }
114
-
115
- interface GameCharacterUnit {
116
- id: number;
117
- gameCharacterId: number;
118
- unit: string;
119
- colorCode: string;
120
- skinColorCode: string;
121
- skinShadowColorCode1: string;
122
- skinShadowColorCode2: string;
96
+ interface SkillDetail {
97
+ cardId?: number;
98
+ scoreUp: number;
99
+ lifeRecovery: number;
123
100
  }
124
101
 
125
- interface UserAreaItem {
126
- areaItemId: number;
127
- level: number;
102
+ interface MusicMeta {
103
+ music_id: number;
104
+ difficulty: string;
105
+ music_time: number;
106
+ event_rate: number;
107
+ base_score: number;
108
+ base_score_auto: number;
109
+ skill_score_solo: number[];
110
+ skill_score_auto: number[];
111
+ skill_score_multi: number[];
112
+ fever_score: number;
113
+ fever_end_time: number;
114
+ tap_count: number;
128
115
  }
129
116
 
130
- interface UserChallengeLiveSoloDeck {
131
- characterId: number;
132
- leader: number;
133
- support1: number;
134
- support2: number | null;
135
- support3: number | null;
136
- support4: number | null;
117
+ declare class LiveCalculator {
118
+ private readonly dataProvider;
119
+ private readonly deckCalculator;
120
+ constructor(dataProvider: DataProvider);
121
+ private getBaseScore;
122
+ private getSkillScore;
123
+ getLiveDetailByDeck(deckDetail: DeckDetail, musicMeta: MusicMeta, liveType: LiveType, skillDetails?: SkillDetail[] | undefined, multiPowerSum?: number): Promise<LiveDetail>;
124
+ private getMultiLiveSkill;
125
+ getLiveDetail(deckCards: UserCard[], musicId: number, musicDiff: string, liveType: LiveType, liveSkills?: LiveSkill[] | undefined): Promise<LiveDetail>;
126
+ getLiveDetailById(deckId: number, musicId: number, musicDiff: string, liveType: LiveType, liveSkills?: LiveSkill[] | undefined): Promise<LiveDetail>;
137
127
  }
138
-
139
- interface UserCharacter {
140
- characterId: number;
141
- characterRank: number;
128
+ interface LiveDetail {
129
+ score: number;
130
+ time: number;
131
+ life: number;
132
+ tap: number;
133
+ }
134
+ interface LiveSkill {
135
+ seq?: number;
136
+ cardId: number;
137
+ }
138
+ declare enum LiveType {
139
+ SOLO = "solo",
140
+ MULTI = "multi",
141
+ AUTO = "auto"
142
142
  }
143
143
 
144
- export { AreaItemLevel, Card, DataProvider, EventCalculator, EventCard, EventDeckBonus, EventRarityBonusRate, GameCharacterUnit, UserAreaItem, UserCard, UserChallengeLiveSoloDeck, UserCharacter, UserDeck };
144
+ export { CardCalculator, CardDetail, CardDetailMap, DataProvider, DeckCalculator, DeckDetail, EventCalculator, LiveCalculator, LiveDetail, LiveSkill, LiveType, SkillDetail };
package/dist/index.mjs CHANGED
@@ -4,11 +4,221 @@ function findOrThrow(arr, p) {
4
4
  throw new Error('object not found');
5
5
  return result;
6
6
  }
7
+ function getOrThrow(map, key) {
8
+ const value = map.get(key);
9
+ if (value === undefined)
10
+ throw new Error('key not found');
11
+ return value;
12
+ }
13
+ function getOrDefault(map, key, defaultValue) {
14
+ const value = map.get(key);
15
+ if (value === undefined)
16
+ return defaultValue;
17
+ return value;
18
+ }
19
+ function computeWithDefault(map, key, defaultValue, action) {
20
+ map.set(key, action(getOrDefault(map, key, defaultValue)));
21
+ }
22
+ function duplicateObj(obj, times) {
23
+ const ret = [];
24
+ for (let i = 0; i < times; ++i)
25
+ ret.push(obj);
26
+ return ret;
27
+ }
28
+ function mapOrUndefined(arr, fun) {
29
+ if (arr === undefined)
30
+ return undefined;
31
+ return arr.map(fun);
32
+ }
33
+
34
+ class CardPowerCalculator {
35
+ dataProvider;
36
+ constructor(dataProvider) {
37
+ this.dataProvider = dataProvider;
38
+ }
39
+ async getCardPower(userCard, card, cardUnits, userAreaItemLevels) {
40
+ const ret = new CardDetailMap();
41
+ const basePower = await this.getCardBasePowers(userCard, card);
42
+ const characterBonus = await this.getCharacterBonusPower(basePower, card.characterId);
43
+ for (const unit of cardUnits) {
44
+ ret.set(unit, 5, 5, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, true, true));
45
+ ret.set(unit, 5, 1, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, true, false));
46
+ ret.set(unit, 1, 5, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, false, true));
47
+ ret.set(unit, 1, 1, await this.getPower(card, basePower, characterBonus, userAreaItemLevels, unit, false, false));
48
+ }
49
+ return ret;
50
+ }
51
+ async getPower(card, basePower, characterBonus, userAreaItemLevels, unit, sameUnit, sameAttr) {
52
+ return basePower.reduce((v, it) => v + it, 0) + characterBonus + await this.getAreaItemBonusPower(userAreaItemLevels, basePower, card.characterId, unit, sameUnit, card.attr, sameAttr);
53
+ }
54
+ async getCardBasePowers(userCard, card) {
55
+ const cardEpisodes = await this.dataProvider.getMasterData('cardEpisodes');
56
+ const masterLessons = await this.dataProvider.getMasterData('masterLessons');
57
+ const ret = [0, 0, 0];
58
+ const cardParameters = card.cardParameters.filter(it => it.cardLevel === userCard.level);
59
+ const params = ['param1', 'param2', 'param3'];
60
+ params.forEach((param, i) => {
61
+ ret[i] = findOrThrow(cardParameters, it => it.cardParameterType === param).power;
62
+ });
63
+ if (userCard.specialTrainingStatus === 'done') {
64
+ ret[0] += card.specialTrainingPower1BonusFixed;
65
+ ret[1] += card.specialTrainingPower2BonusFixed;
66
+ ret[2] += card.specialTrainingPower3BonusFixed;
67
+ }
68
+ const episodes = userCard.episodes.filter(it => it.scenarioStatus === 'already_read')
69
+ .map(it => findOrThrow(cardEpisodes, e => e.id === it.cardEpisodeId));
70
+ for (const episode of episodes) {
71
+ ret[0] += episode.power1BonusFixed;
72
+ ret[1] += episode.power2BonusFixed;
73
+ ret[2] += episode.power3BonusFixed;
74
+ }
75
+ const usedMasterLessons = masterLessons
76
+ .filter((it) => it.cardRarityType === card.cardRarityType && it.masterRank <= userCard.masterRank);
77
+ for (const masterLesson of usedMasterLessons) {
78
+ ret[0] += masterLesson.power1BonusFixed;
79
+ ret[1] += masterLesson.power2BonusFixed;
80
+ ret[2] += masterLesson.power3BonusFixed;
81
+ }
82
+ return ret;
83
+ }
84
+ async getAreaItemBonusPower(userAreaItemLevels, basePower, characterId, unit, sameUnit, attr, sameAttr) {
85
+ const usedAreaItems = userAreaItemLevels.filter(it => (it.targetUnit === 'any' || it.targetUnit === unit) &&
86
+ (it.targetCardAttr === 'any' || it.targetCardAttr === attr) &&
87
+ (it.targetGameCharacterId === undefined || it.targetGameCharacterId === characterId));
88
+ const areaItemBonus = [0, 0, 0];
89
+ for (const areaItem of usedAreaItems) {
90
+ const allMatch = (areaItem.targetUnit !== 'any' && sameUnit) || (areaItem.targetCardAttr !== 'any' && sameAttr);
91
+ areaItemBonus[0] += allMatch ? areaItem.power1AllMatchBonusRate : areaItem.power1BonusRate;
92
+ areaItemBonus[1] += allMatch ? areaItem.power2AllMatchBonusRate : areaItem.power2BonusRate;
93
+ areaItemBonus[2] += allMatch ? areaItem.power3AllMatchBonusRate : areaItem.power3BonusRate;
94
+ }
95
+ return basePower.reduce((v, it, i) => v + Math.floor(it * areaItemBonus[i] / 100), 0);
96
+ }
97
+ async getCharacterBonusPower(basePower, characterId) {
98
+ const characterRanks = await this.dataProvider.getMasterData('characterRanks');
99
+ const userCharacters = await this.dataProvider.getUserData('userCharacters');
100
+ const userCharacter = findOrThrow(userCharacters, it => it.characterId === characterId);
101
+ const characterRank = findOrThrow(characterRanks, it => it.characterId === userCharacter.characterId && it.characterRank === userCharacter.characterRank);
102
+ const rates = [characterRank.power1BonusRate, characterRank.power2BonusRate, characterRank.power3BonusRate];
103
+ return rates.reduce((v, it, i) => v + Math.floor(basePower[i] * it / 100), 0);
104
+ }
105
+ }
106
+
107
+ class CardSkillCalculator {
108
+ dataProvider;
109
+ constructor(dataProvider) {
110
+ this.dataProvider = dataProvider;
111
+ }
112
+ async getCardSkill(userCard, card) {
113
+ const scoreUpMap = new CardDetailMap();
114
+ const detail = await this.getSkillDetail(userCard, card);
115
+ if (detail.scoreUpEnhance !== undefined) {
116
+ for (let i = 1; i <= 5; ++i) {
117
+ const scoreUp = detail.scoreUp + (i === 5 ? 5 : (i - 1)) * detail.scoreUpEnhance.value;
118
+ scoreUpMap.set(detail.scoreUpEnhance.unit, i, 1, scoreUp);
119
+ }
120
+ }
121
+ scoreUpMap.set('any', 1, 1, detail.scoreUp);
122
+ return { scoreUp: scoreUpMap, lifeRecovery: detail.lifeRecovery };
123
+ }
124
+ async getSkillDetail(userCard, card) {
125
+ const skills = await this.dataProvider.getMasterData('skills');
126
+ const skill = findOrThrow(skills, it => it.id === card.skillId);
127
+ const ret = { scoreUp: 0, lifeRecovery: 0 };
128
+ for (const skillEffect of skill.skillEffects) {
129
+ const skillEffectDetail = findOrThrow(skillEffect.skillEffectDetails, it => it.level === userCard.skillLevel);
130
+ if (skillEffect.skillEffectType === 'score_up' ||
131
+ skillEffect.skillEffectType === 'score_up_condition_life' ||
132
+ skillEffect.skillEffectType === 'score_up_keep') {
133
+ const current = skillEffectDetail.activateEffectValue;
134
+ if (skillEffect.skillEnhance !== undefined) {
135
+ ret.scoreUpEnhance = {
136
+ unit: skillEffect.skillEnhance.skillEnhanceCondition.unit,
137
+ value: skillEffect.skillEnhance.activateEffectValue
138
+ };
139
+ }
140
+ ret.scoreUp = Math.max(ret.scoreUp, current);
141
+ }
142
+ else if (skillEffect.skillEffectType === 'life_recovery') {
143
+ ret.lifeRecovery += skillEffectDetail.activateEffectValue;
144
+ }
145
+ }
146
+ return ret;
147
+ }
148
+ }
149
+
150
+ class CardCalculator {
151
+ dataProvider;
152
+ powerCalculator;
153
+ skillCalculator;
154
+ constructor(dataProvider) {
155
+ this.dataProvider = dataProvider;
156
+ this.powerCalculator = new CardPowerCalculator(dataProvider);
157
+ this.skillCalculator = new CardSkillCalculator(dataProvider);
158
+ }
159
+ async getCardUnits(card) {
160
+ const gameCharacters = await this.dataProvider.getMasterData('gameCharacters');
161
+ const units = [];
162
+ if (card.supportUnit !== 'none')
163
+ units.push(card.supportUnit);
164
+ units.push(findOrThrow(gameCharacters, it => it.id === card.characterId).unit);
165
+ return units;
166
+ }
167
+ async getCardDetail(userCard, userAreaItemLevels) {
168
+ const cards = await this.dataProvider.getMasterData('cards');
169
+ const card = findOrThrow(cards, it => it.id === userCard.cardId);
170
+ const units = await this.getCardUnits(card);
171
+ const skill = await this.skillCalculator.getCardSkill(userCard, card);
172
+ const power = await this.powerCalculator.getCardPower(userCard, card, units, userAreaItemLevels);
173
+ return {
174
+ cardId: card.id,
175
+ units,
176
+ attr: card.attr,
177
+ power,
178
+ scoreSkill: skill.scoreUp,
179
+ lifeSkill: skill.lifeRecovery
180
+ };
181
+ }
182
+ }
183
+ class CardDetailMap {
184
+ min = Number.MAX_SAFE_INTEGER;
185
+ max = Number.MIN_SAFE_INTEGER;
186
+ values = new Map();
187
+ set(unit, unitMember, attrMember, value) {
188
+ this.min = Math.min(this.min, value);
189
+ this.max = Math.max(this.max, value);
190
+ this.values.set(CardDetailMap.getKey(unit, unitMember, attrMember), value);
191
+ }
192
+ get(unit, unitMember, attrMember) {
193
+ const attrMember0 = attrMember === 5 ? 5 : 1;
194
+ let best = this.getInternal(unit, unitMember, attrMember0);
195
+ if (best !== undefined)
196
+ return best;
197
+ best = this.getInternal(unit, unitMember === 5 ? 5 : 1, attrMember0);
198
+ if (best !== undefined)
199
+ return best;
200
+ best = this.getInternal('any', 1, 1);
201
+ if (best !== undefined)
202
+ return best;
203
+ throw new Error('case not found');
204
+ }
205
+ getInternal(unit, unitMember, attrMember) {
206
+ return this.values.get(CardDetailMap.getKey(unit, unitMember, attrMember));
207
+ }
208
+ static getKey(unit, unitMember, attrMember) {
209
+ return `${unit}-${unitMember}-${attrMember}`;
210
+ }
211
+ isCertainlyLessThen(another) {
212
+ return this.max < another.min;
213
+ }
214
+ }
7
215
 
8
216
  class DeckCalculator {
9
217
  dataProvider;
218
+ cardCalculator;
10
219
  constructor(dataProvider) {
11
220
  this.dataProvider = dataProvider;
221
+ this.cardCalculator = new CardCalculator(dataProvider);
12
222
  }
13
223
  async getDeck(deckId) {
14
224
  const userDecks = await this.dataProvider.getUserData('userDecks');
@@ -22,14 +232,49 @@ class DeckCalculator {
22
232
  async getDeckCardsById(deckId) {
23
233
  return await this.getDeckCards(await this.getDeck(deckId));
24
234
  }
235
+ async getHonorBonusPower() {
236
+ const honors = await this.dataProvider.getMasterData('honors');
237
+ const userHonors = await this.dataProvider.getUserData('userHonors');
238
+ return userHonors
239
+ .map(userHonor => {
240
+ const honor = findOrThrow(honors, it => it.id === userHonor.honorId);
241
+ return findOrThrow(honor.levels, it => it.level === userHonor.level);
242
+ })
243
+ .reduce((v, it) => v + it.bonus, 0);
244
+ }
245
+ async getDeckDetailByCards(cardDetails, honorBonus) {
246
+ const map = new Map();
247
+ for (const cardDetail of cardDetails) {
248
+ computeWithDefault(map, cardDetail.attr, 0, it => it + 1);
249
+ cardDetail.units.forEach(key => { computeWithDefault(map, key, 0, it => it + 1); });
250
+ }
251
+ const power = cardDetails.reduce((v, cardDetail) => v + cardDetail.units.reduce((vv, unit) => Math.max(vv, cardDetail.power.get(unit, getOrThrow(map, unit), getOrThrow(map, cardDetail.attr))), 0), 0) + honorBonus;
252
+ const skill = cardDetails.map(cardDetail => {
253
+ const scoreUp = cardDetail.units.reduce((vv, unit) => Math.max(vv, cardDetail.scoreSkill.get(unit, getOrThrow(map, unit), 1)), 0);
254
+ return {
255
+ cardId: cardDetail.cardId,
256
+ scoreUp,
257
+ lifeRecovery: cardDetail.lifeSkill
258
+ };
259
+ });
260
+ return { power, skill };
261
+ }
262
+ async getDeckDetail(deckCards) {
263
+ const areaItemLevels = await this.dataProvider.getMasterData('areaItemLevels');
264
+ const userAreas = await this.dataProvider.getUserData('userAreas');
265
+ const userItemLevels = userAreas.flatMap(it => it.areaItems).map(areaItem => findOrThrow(areaItemLevels, it => it.areaItemId === areaItem.areaItemId && it.level === areaItem.level));
266
+ const cardDetails = await Promise.all(deckCards.map(async (it) => await this.cardCalculator.getCardDetail(it, userItemLevels)));
267
+ return await this.getDeckDetailByCards(cardDetails, await this.getHonorBonusPower());
268
+ }
269
+ async getDeckDetailById(deckId) {
270
+ return await this.getDeckDetail(await this.getDeckCardsById(deckId));
271
+ }
25
272
  }
26
273
 
27
- class EventCalculator {
274
+ class CardEventCalculator {
28
275
  dataProvider;
29
- deckCalculator;
30
276
  constructor(dataProvider) {
31
277
  this.dataProvider = dataProvider;
32
- this.deckCalculator = new DeckCalculator(dataProvider);
33
278
  }
34
279
  async getEventDeckBonus(eventId, card) {
35
280
  const eventDeckBonuses = await this.dataProvider.getMasterData('eventDeckBonuses');
@@ -63,13 +308,96 @@ class EventCalculator {
63
308
  eventBonus += masterRankBonus.bonusRate;
64
309
  return eventBonus;
65
310
  }
311
+ }
312
+
313
+ class EventCalculator {
314
+ dataProvider;
315
+ deckCalculator;
316
+ cardEventCalculator;
317
+ constructor(dataProvider) {
318
+ this.dataProvider = dataProvider;
319
+ this.deckCalculator = new DeckCalculator(dataProvider);
320
+ this.cardEventCalculator = new CardEventCalculator(dataProvider);
321
+ }
66
322
  async getDeckEventBonus(userDeck, eventId) {
67
323
  const deckCards = await this.deckCalculator.getDeckCards(userDeck);
68
- return await deckCards.reduce(async (v, it) => await this.getCardEventBonus(it, eventId) + await v, Promise.resolve(0));
324
+ return await deckCards.reduce(async (v, it) => await v + await this.cardEventCalculator.getCardEventBonus(it, eventId), Promise.resolve(0));
69
325
  }
70
326
  async getDeckEventBonusById(deckId, eventId) {
71
327
  return await this.getDeckEventBonus(await this.deckCalculator.getDeck(deckId), eventId);
72
328
  }
73
329
  }
74
330
 
75
- export { EventCalculator };
331
+ class LiveCalculator {
332
+ dataProvider;
333
+ deckCalculator;
334
+ constructor(dataProvider) {
335
+ this.dataProvider = dataProvider;
336
+ this.deckCalculator = new DeckCalculator(dataProvider);
337
+ }
338
+ getBaseScore(musicMeta, liveType) {
339
+ switch (liveType) {
340
+ case LiveType.SOLO:
341
+ return musicMeta.base_score;
342
+ case LiveType.MULTI:
343
+ return musicMeta.base_score + musicMeta.fever_score;
344
+ case LiveType.AUTO:
345
+ return musicMeta.base_score_auto;
346
+ }
347
+ }
348
+ getSkillScore(musicMeta, liveType) {
349
+ switch (liveType) {
350
+ case LiveType.SOLO:
351
+ return musicMeta.skill_score_solo;
352
+ case LiveType.MULTI:
353
+ return musicMeta.skill_score_multi;
354
+ case LiveType.AUTO:
355
+ return musicMeta.skill_score_auto;
356
+ }
357
+ }
358
+ async getLiveDetailByDeck(deckDetail, musicMeta, liveType, skillDetails = undefined, multiPowerSum = 0) {
359
+ const bestSkill = skillDetails === undefined;
360
+ const skills = bestSkill
361
+ ? [...deckDetail.skill, deckDetail.skill[0]].sort((a, b) => a.scoreUp - b.scoreUp)
362
+ : skillDetails;
363
+ const baseRate = this.getBaseScore(musicMeta, liveType);
364
+ const skillRate = bestSkill
365
+ ? [...this.getSkillScore(musicMeta, liveType)].sort((a, b) => a - b)
366
+ : this.getSkillScore(musicMeta, liveType);
367
+ const rate = baseRate + skills.reduce((v, it, i) => v + it.scoreUp * skillRate[i] / 100, 0);
368
+ const life = skills.reduce((v, it) => v + it.lifeRecovery, 0);
369
+ const powerSum = multiPowerSum === 0 ? 5 * deckDetail.power : multiPowerSum;
370
+ const activeBonus = liveType === LiveType.MULTI ? 5 * 0.015 * powerSum : 0;
371
+ return {
372
+ score: Math.floor(rate * deckDetail.power * 4 + activeBonus),
373
+ time: musicMeta.music_time,
374
+ life: Math.min(2000, life + 1000),
375
+ tap: musicMeta.tap_count
376
+ };
377
+ }
378
+ getMultiLiveSkill(deckDetail) {
379
+ const scoreUp = deckDetail.skill.reduce((v, it, i) => v + (i === 0 ? it.scoreUp : (it.scoreUp / 5)), 0);
380
+ const lifeRecovery = deckDetail.skill[0].lifeRecovery;
381
+ return { scoreUp, lifeRecovery };
382
+ }
383
+ async getLiveDetail(deckCards, musicId, musicDiff, liveType, liveSkills = undefined) {
384
+ const musicMetas = await this.dataProvider.getMusicMeta();
385
+ const musicMeta = findOrThrow(musicMetas, it => it.music_id === musicId && it.difficulty === musicDiff);
386
+ const deckDetail = await this.deckCalculator.getDeckDetail(deckCards);
387
+ const skills = liveType === LiveType.MULTI
388
+ ? duplicateObj(this.getMultiLiveSkill(deckDetail), 6)
389
+ : (mapOrUndefined(liveSkills, liveSkill => findOrThrow(deckDetail.skill, it => it.cardId === liveSkill.cardId)));
390
+ return await this.getLiveDetailByDeck(deckDetail, musicMeta, liveType, skills);
391
+ }
392
+ async getLiveDetailById(deckId, musicId, musicDiff, liveType, liveSkills = undefined) {
393
+ return await this.getLiveDetail(await this.deckCalculator.getDeckCardsById(deckId), musicId, musicDiff, liveType, liveSkills);
394
+ }
395
+ }
396
+ var LiveType;
397
+ (function (LiveType) {
398
+ LiveType["SOLO"] = "solo";
399
+ LiveType["MULTI"] = "multi";
400
+ LiveType["AUTO"] = "auto";
401
+ })(LiveType || (LiveType = {}));
402
+
403
+ export { CardCalculator, CardDetailMap, DeckCalculator, EventCalculator, LiveCalculator, LiveType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sekai-calculator",
3
- "version": "0.0.8",
3
+ "version": "0.1.0",
4
4
  "description": "Project SEKAI Calculator for deck power, live score, event point and more.",
5
5
  "type": "module",
6
6
  "types": "dist/index.d.ts",