sekai-calculator 0.4.3 → 0.5.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/dist/index.cjs CHANGED
@@ -78,15 +78,15 @@ class DeckService {
78
78
  .map(async (id) => await this.getUserCard(id === null ? 0 : id)));
79
79
  }
80
80
  static toUserChallengeLiveSoloDeck(userCards, characterId) {
81
- if (userCards.length !== 5)
82
- throw new Error('deck card should be 5');
81
+ if (userCards.length < 2)
82
+ throw new Error('deck card should more than 1');
83
83
  return {
84
84
  characterId,
85
85
  leader: userCards[0].cardId,
86
86
  support1: userCards[1].cardId,
87
- support2: userCards[2].cardId,
88
- support3: userCards[3].cardId,
89
- support4: userCards[4].cardId
87
+ support2: userCards.length < 3 ? null : userCards[2].cardId,
88
+ support3: userCards.length < 4 ? null : userCards[3].cardId,
89
+ support4: userCards.length < 5 ? null : userCards[4].cardId
90
90
  };
91
91
  }
92
92
  }
@@ -300,13 +300,40 @@ class CardCalculator {
300
300
  units.push(findOrThrow(gameCharacters, it => it.id === card.characterId).unit);
301
301
  return units;
302
302
  }
303
- async getCardDetail(userCard, userAreaItemLevels, eventId = 0) {
303
+ async applyCardConfig(userCard, card, { rankMax = false, episodeRead = false, masterMax = false, skillMax = false }) {
304
+ if (!rankMax && !episodeRead && !masterMax && !skillMax)
305
+ return userCard;
306
+ const cardRarities = await this.dataProvider.getMasterData('cardRarities');
307
+ const cardRarity = findOrThrow(cardRarities, it => it.cardRarityType === card.cardRarityType);
308
+ const ret = JSON.parse(JSON.stringify(userCard));
309
+ if (rankMax) {
310
+ if (cardRarity.trainingMaxLevel !== undefined) {
311
+ ret.level = cardRarity.trainingMaxLevel;
312
+ ret.specialTrainingStatus = 'done';
313
+ }
314
+ else {
315
+ ret.level = cardRarity.maxLevel;
316
+ }
317
+ }
318
+ if (episodeRead) {
319
+ ret.episodes.forEach(it => { it.scenarioStatus = 'already_read'; });
320
+ }
321
+ if (masterMax) {
322
+ ret.masterRank = 5;
323
+ }
324
+ if (skillMax) {
325
+ ret.skillLevel = cardRarity.maxSkillLevel;
326
+ }
327
+ return ret;
328
+ }
329
+ async getCardDetail(userCard, userAreaItemLevels, config = {}, eventId = 0) {
304
330
  const cards = await this.dataProvider.getMasterData('cards');
305
331
  const card = findOrThrow(cards, it => it.id === userCard.cardId);
306
332
  const units = await this.getCardUnits(card);
307
- const skill = await this.skillCalculator.getCardSkill(userCard, card);
308
- const power = await this.powerCalculator.getCardPower(userCard, card, units, userAreaItemLevels);
309
- const eventBonus = eventId === 0 ? undefined : await this.eventCalculator.getCardEventBonus(userCard, eventId);
333
+ const userCard0 = await this.applyCardConfig(userCard, card, config);
334
+ const skill = await this.skillCalculator.getCardSkill(userCard0, card);
335
+ const power = await this.powerCalculator.getCardPower(userCard0, card, units, userAreaItemLevels);
336
+ const eventBonus = eventId === 0 ? undefined : await this.eventCalculator.getCardEventBonus(userCard0, eventId);
310
337
  return {
311
338
  cardId: card.id,
312
339
  characterId: card.characterId,
@@ -318,11 +345,11 @@ class CardCalculator {
318
345
  eventBonus
319
346
  };
320
347
  }
321
- async batchGetCardDetail(userCards, eventId = 0) {
348
+ async batchGetCardDetail(userCards, config = {}, eventId = 0) {
322
349
  const areaItemLevels = await this.dataProvider.getMasterData('areaItemLevels');
323
350
  const userAreas = await this.dataProvider.getUserData('userAreas');
324
351
  const userItemLevels = userAreas.flatMap(it => it.areaItems).map(areaItem => findOrThrow(areaItemLevels, it => it.areaItemId === areaItem.areaItemId && it.level === areaItem.level));
325
- return await Promise.all(userCards.map(async (it) => await this.getCardDetail(it, userItemLevels, eventId)));
352
+ return await Promise.all(userCards.map(async (it) => await this.getCardDetail(it, userItemLevels, config, eventId)));
326
353
  }
327
354
  static isCertainlyLessThan(cardDetail0, cardDetail1) {
328
355
  return cardDetail0.power.isCertainlyLessThen(cardDetail1.power) &&
@@ -545,7 +572,7 @@ class BaseDeckRecommend {
545
572
  }
546
573
  static filterCard(cardDetails) {
547
574
  let afterFilter = cardDetails;
548
- for (const minBonus of [65, 50, 40, 25, 15, 0]) {
575
+ for (const minBonus of [55, 50, 45, 40, 30, 25, 15, 5, 0]) {
549
576
  const bonusFilter = cardDetails.filter(cardDetail => !(cardDetail.eventBonus !== undefined && cardDetail.eventBonus < minBonus));
550
577
  if (this.canMakeEventDeck(bonusFilter)) {
551
578
  afterFilter = bonusFilter;
@@ -593,8 +620,8 @@ class BaseDeckRecommend {
593
620
  throw new Error(`Cannot find deck in ${cardDetails.length} cards`);
594
621
  return ans;
595
622
  }
596
- async recommendHighScoreDeck(userCards, musicMeta, scoreFunc, limit = 1, eventId = 0, isChallengeLive = false, member = 5) {
597
- const cards = await this.cardCalculator.batchGetCardDetail(userCards, eventId);
623
+ async recommendHighScoreDeck(userCards, scoreFunc, { musicMeta, limit = 1, member = 5, cardConfig = {} }, eventId = 0, isChallengeLive = false) {
624
+ const cards = await this.cardCalculator.batchGetCardDetail(userCards, cardConfig, eventId);
598
625
  let cardDetails = (isChallengeLive || eventId === 0) ? cards : BaseDeckRecommend.filterCard(cards);
599
626
  cardDetails = cardDetails.sort((a, b) => a.cardId - b.cardId);
600
627
  const honorBonus = await this.deckCalculator.getHonorBonusPower();
@@ -615,12 +642,12 @@ class ChallengeLiveDeckRecommend {
615
642
  this.dataProvider = dataProvider;
616
643
  this.baseRecommend = new BaseDeckRecommend(dataProvider);
617
644
  }
618
- async recommendChallengeLiveDeck(characterId, musicMeta, limit = 1, member = 5) {
645
+ async recommendChallengeLiveDeck(characterId, config) {
619
646
  const userCards = await this.dataProvider.getUserData('userCards');
620
647
  const cards = await this.dataProvider.getMasterData('cards');
621
648
  const characterCards = userCards
622
649
  .filter(userCard => findOrThrow(cards, it => it.id === userCard.cardId).characterId === characterId);
623
- const recommend = await this.baseRecommend.recommendHighScoreDeck(characterCards, musicMeta, BaseDeckRecommend.getLiveScoreFunction(exports.LiveType.SOLO), limit, 0, true, member);
650
+ const recommend = await this.baseRecommend.recommendHighScoreDeck(characterCards, BaseDeckRecommend.getLiveScoreFunction(exports.LiveType.SOLO), config, 0, true);
624
651
  return recommend.map(it => {
625
652
  return {
626
653
  score: it.score,
@@ -638,9 +665,9 @@ class EventDeckRecommend {
638
665
  this.dataProvider = dataProvider;
639
666
  this.baseRecommend = new BaseDeckRecommend(dataProvider);
640
667
  }
641
- async recommendEventDeck(eventId, musicMeta, liveType, limit = 1) {
668
+ async recommendEventDeck(eventId, liveType, config) {
642
669
  const userCards = await this.dataProvider.getUserData('userCards');
643
- const recommend = await this.baseRecommend.recommendHighScoreDeck(userCards, musicMeta, BaseDeckRecommend.getEventPointFunction(liveType), limit, eventId);
670
+ const recommend = await this.baseRecommend.recommendHighScoreDeck(userCards, BaseDeckRecommend.getEventPointFunction(liveType), config, eventId);
644
671
  return recommend.map(it => {
645
672
  return {
646
673
  point: it.score,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  interface DataProvider {
2
2
  getMasterData: (key: string) => Promise<any>;
3
+ getUserDataAll: () => Promise<any>;
3
4
  getUserData: (key: string) => Promise<any>;
4
5
  getMusicMeta: () => Promise<any>;
5
6
  }
@@ -81,8 +82,9 @@ declare class CardCalculator {
81
82
  private readonly eventCalculator;
82
83
  constructor(dataProvider: DataProvider);
83
84
  private getCardUnits;
84
- getCardDetail(userCard: UserCard, userAreaItemLevels: AreaItemLevel[], eventId?: number): Promise<CardDetail>;
85
- batchGetCardDetail(userCards: UserCard[], eventId?: number): Promise<CardDetail[]>;
85
+ private applyCardConfig;
86
+ getCardDetail(userCard: UserCard, userAreaItemLevels: AreaItemLevel[], config?: CardConfig, eventId?: number): Promise<CardDetail>;
87
+ batchGetCardDetail(userCards: UserCard[], config?: CardConfig, eventId?: number): Promise<CardDetail[]>;
86
88
  static isCertainlyLessThan(cardDetail0: CardDetail, cardDetail1: CardDetail): boolean;
87
89
  }
88
90
  interface CardDetail {
@@ -95,6 +97,12 @@ interface CardDetail {
95
97
  lifeSkill: number;
96
98
  eventBonus?: number;
97
99
  }
100
+ interface CardConfig {
101
+ rankMax?: boolean;
102
+ episodeRead?: boolean;
103
+ masterMax?: boolean;
104
+ skillMax?: boolean;
105
+ }
98
106
 
99
107
  declare class DeckService {
100
108
  private readonly dataProvider;
@@ -250,11 +258,18 @@ declare class EventCalculator {
250
258
  static getDeckEventPoint(deckCards: CardDetail[], honorBonus: number, musicMeta: MusicMeta, liveType: LiveType): number;
251
259
  }
252
260
 
261
+ interface DeckRecommendConfig {
262
+ musicMeta: MusicMeta;
263
+ limit?: number;
264
+ member?: number;
265
+ cardConfig?: CardConfig;
266
+ }
267
+
253
268
  declare class ChallengeLiveDeckRecommend {
254
269
  private readonly dataProvider;
255
270
  private readonly baseRecommend;
256
271
  constructor(dataProvider: DataProvider);
257
- recommendChallengeLiveDeck(characterId: number, musicMeta: MusicMeta, limit?: number, member?: number): Promise<Array<{
272
+ recommendChallengeLiveDeck(characterId: number, config: DeckRecommendConfig): Promise<Array<{
258
273
  score: number;
259
274
  power: number;
260
275
  deck: UserChallengeLiveSoloDeck;
@@ -265,7 +280,7 @@ declare class EventDeckRecommend {
265
280
  private readonly dataProvider;
266
281
  private readonly baseRecommend;
267
282
  constructor(dataProvider: DataProvider);
268
- recommendEventDeck(eventId: number, musicMeta: MusicMeta, liveType: LiveType, limit?: number): Promise<Array<{
283
+ recommendEventDeck(eventId: number, liveType: LiveType, config: DeckRecommendConfig): Promise<Array<{
269
284
  point: number;
270
285
  power: number;
271
286
  eventBonus?: number;
@@ -303,6 +318,14 @@ interface CardEpisode {
303
318
  cardEpisodePartType: string;
304
319
  }
305
320
 
321
+ interface CardRarity {
322
+ cardRarityType: string;
323
+ seq: number;
324
+ maxLevel: number;
325
+ trainingMaxLevel?: number;
326
+ maxSkillLevel: number;
327
+ }
328
+
306
329
  interface CharacterRank {
307
330
  id: number;
308
331
  characterId: number;
@@ -345,9 +368,9 @@ interface GameCharacter {
345
368
  id: number;
346
369
  seq: number;
347
370
  resourceId: number;
348
- firstName: string;
371
+ firstName?: string;
349
372
  givenName: string;
350
- firstNameRuby: string;
373
+ firstNameRuby?: string;
351
374
  givenNameRuby: string;
352
375
  gender: string;
353
376
  height: number;
@@ -492,4 +515,4 @@ interface UserHonor {
492
515
  level: number;
493
516
  }
494
517
 
495
- export { AreaItemLevel, Card, CardCalculator, CardDetail, CardEpisode, CardEventCalculator, CardPowerCalculator, CardSkillCalculator, ChallengeLiveDeckRecommend, CharacterRank, DataProvider, DeckCalculator, DeckDetail, DeckService, EventCalculator, EventCard, EventDeckBonus, EventDeckRecommend, EventRarityBonusRate, GameCharacter, GameCharacterUnit, Honor, LiveCalculator, LiveDetail, LiveSkill, LiveType, MasterLesson, MusicMeta, MusicRecommend, Skill, SkillDetail, User, UserArea, UserCard, UserChallengeLiveSoloDeck, UserCharacter, UserDeck, UserHonor };
518
+ export { AreaItemLevel, Card, CardCalculator, CardConfig, CardDetail, CardEpisode, CardEventCalculator, CardPowerCalculator, CardRarity, CardSkillCalculator, ChallengeLiveDeckRecommend, CharacterRank, DataProvider, DeckCalculator, DeckDetail, DeckService, EventCalculator, EventCard, EventDeckBonus, EventDeckRecommend, EventRarityBonusRate, GameCharacter, GameCharacterUnit, Honor, LiveCalculator, LiveDetail, LiveSkill, LiveType, MasterLesson, MusicMeta, MusicRecommend, Skill, SkillDetail, User, UserArea, UserCard, UserChallengeLiveSoloDeck, UserCharacter, UserDeck, UserHonor };
package/dist/index.mjs CHANGED
@@ -76,15 +76,15 @@ class DeckService {
76
76
  .map(async (id) => await this.getUserCard(id === null ? 0 : id)));
77
77
  }
78
78
  static toUserChallengeLiveSoloDeck(userCards, characterId) {
79
- if (userCards.length !== 5)
80
- throw new Error('deck card should be 5');
79
+ if (userCards.length < 2)
80
+ throw new Error('deck card should more than 1');
81
81
  return {
82
82
  characterId,
83
83
  leader: userCards[0].cardId,
84
84
  support1: userCards[1].cardId,
85
- support2: userCards[2].cardId,
86
- support3: userCards[3].cardId,
87
- support4: userCards[4].cardId
85
+ support2: userCards.length < 3 ? null : userCards[2].cardId,
86
+ support3: userCards.length < 4 ? null : userCards[3].cardId,
87
+ support4: userCards.length < 5 ? null : userCards[4].cardId
88
88
  };
89
89
  }
90
90
  }
@@ -298,13 +298,40 @@ class CardCalculator {
298
298
  units.push(findOrThrow(gameCharacters, it => it.id === card.characterId).unit);
299
299
  return units;
300
300
  }
301
- async getCardDetail(userCard, userAreaItemLevels, eventId = 0) {
301
+ async applyCardConfig(userCard, card, { rankMax = false, episodeRead = false, masterMax = false, skillMax = false }) {
302
+ if (!rankMax && !episodeRead && !masterMax && !skillMax)
303
+ return userCard;
304
+ const cardRarities = await this.dataProvider.getMasterData('cardRarities');
305
+ const cardRarity = findOrThrow(cardRarities, it => it.cardRarityType === card.cardRarityType);
306
+ const ret = JSON.parse(JSON.stringify(userCard));
307
+ if (rankMax) {
308
+ if (cardRarity.trainingMaxLevel !== undefined) {
309
+ ret.level = cardRarity.trainingMaxLevel;
310
+ ret.specialTrainingStatus = 'done';
311
+ }
312
+ else {
313
+ ret.level = cardRarity.maxLevel;
314
+ }
315
+ }
316
+ if (episodeRead) {
317
+ ret.episodes.forEach(it => { it.scenarioStatus = 'already_read'; });
318
+ }
319
+ if (masterMax) {
320
+ ret.masterRank = 5;
321
+ }
322
+ if (skillMax) {
323
+ ret.skillLevel = cardRarity.maxSkillLevel;
324
+ }
325
+ return ret;
326
+ }
327
+ async getCardDetail(userCard, userAreaItemLevels, config = {}, eventId = 0) {
302
328
  const cards = await this.dataProvider.getMasterData('cards');
303
329
  const card = findOrThrow(cards, it => it.id === userCard.cardId);
304
330
  const units = await this.getCardUnits(card);
305
- const skill = await this.skillCalculator.getCardSkill(userCard, card);
306
- const power = await this.powerCalculator.getCardPower(userCard, card, units, userAreaItemLevels);
307
- const eventBonus = eventId === 0 ? undefined : await this.eventCalculator.getCardEventBonus(userCard, eventId);
331
+ const userCard0 = await this.applyCardConfig(userCard, card, config);
332
+ const skill = await this.skillCalculator.getCardSkill(userCard0, card);
333
+ const power = await this.powerCalculator.getCardPower(userCard0, card, units, userAreaItemLevels);
334
+ const eventBonus = eventId === 0 ? undefined : await this.eventCalculator.getCardEventBonus(userCard0, eventId);
308
335
  return {
309
336
  cardId: card.id,
310
337
  characterId: card.characterId,
@@ -316,11 +343,11 @@ class CardCalculator {
316
343
  eventBonus
317
344
  };
318
345
  }
319
- async batchGetCardDetail(userCards, eventId = 0) {
346
+ async batchGetCardDetail(userCards, config = {}, eventId = 0) {
320
347
  const areaItemLevels = await this.dataProvider.getMasterData('areaItemLevels');
321
348
  const userAreas = await this.dataProvider.getUserData('userAreas');
322
349
  const userItemLevels = userAreas.flatMap(it => it.areaItems).map(areaItem => findOrThrow(areaItemLevels, it => it.areaItemId === areaItem.areaItemId && it.level === areaItem.level));
323
- return await Promise.all(userCards.map(async (it) => await this.getCardDetail(it, userItemLevels, eventId)));
350
+ return await Promise.all(userCards.map(async (it) => await this.getCardDetail(it, userItemLevels, config, eventId)));
324
351
  }
325
352
  static isCertainlyLessThan(cardDetail0, cardDetail1) {
326
353
  return cardDetail0.power.isCertainlyLessThen(cardDetail1.power) &&
@@ -543,7 +570,7 @@ class BaseDeckRecommend {
543
570
  }
544
571
  static filterCard(cardDetails) {
545
572
  let afterFilter = cardDetails;
546
- for (const minBonus of [65, 50, 40, 25, 15, 0]) {
573
+ for (const minBonus of [55, 50, 45, 40, 30, 25, 15, 5, 0]) {
547
574
  const bonusFilter = cardDetails.filter(cardDetail => !(cardDetail.eventBonus !== undefined && cardDetail.eventBonus < minBonus));
548
575
  if (this.canMakeEventDeck(bonusFilter)) {
549
576
  afterFilter = bonusFilter;
@@ -591,8 +618,8 @@ class BaseDeckRecommend {
591
618
  throw new Error(`Cannot find deck in ${cardDetails.length} cards`);
592
619
  return ans;
593
620
  }
594
- async recommendHighScoreDeck(userCards, musicMeta, scoreFunc, limit = 1, eventId = 0, isChallengeLive = false, member = 5) {
595
- const cards = await this.cardCalculator.batchGetCardDetail(userCards, eventId);
621
+ async recommendHighScoreDeck(userCards, scoreFunc, { musicMeta, limit = 1, member = 5, cardConfig = {} }, eventId = 0, isChallengeLive = false) {
622
+ const cards = await this.cardCalculator.batchGetCardDetail(userCards, cardConfig, eventId);
596
623
  let cardDetails = (isChallengeLive || eventId === 0) ? cards : BaseDeckRecommend.filterCard(cards);
597
624
  cardDetails = cardDetails.sort((a, b) => a.cardId - b.cardId);
598
625
  const honorBonus = await this.deckCalculator.getHonorBonusPower();
@@ -613,12 +640,12 @@ class ChallengeLiveDeckRecommend {
613
640
  this.dataProvider = dataProvider;
614
641
  this.baseRecommend = new BaseDeckRecommend(dataProvider);
615
642
  }
616
- async recommendChallengeLiveDeck(characterId, musicMeta, limit = 1, member = 5) {
643
+ async recommendChallengeLiveDeck(characterId, config) {
617
644
  const userCards = await this.dataProvider.getUserData('userCards');
618
645
  const cards = await this.dataProvider.getMasterData('cards');
619
646
  const characterCards = userCards
620
647
  .filter(userCard => findOrThrow(cards, it => it.id === userCard.cardId).characterId === characterId);
621
- const recommend = await this.baseRecommend.recommendHighScoreDeck(characterCards, musicMeta, BaseDeckRecommend.getLiveScoreFunction(LiveType.SOLO), limit, 0, true, member);
648
+ const recommend = await this.baseRecommend.recommendHighScoreDeck(characterCards, BaseDeckRecommend.getLiveScoreFunction(LiveType.SOLO), config, 0, true);
622
649
  return recommend.map(it => {
623
650
  return {
624
651
  score: it.score,
@@ -636,9 +663,9 @@ class EventDeckRecommend {
636
663
  this.dataProvider = dataProvider;
637
664
  this.baseRecommend = new BaseDeckRecommend(dataProvider);
638
665
  }
639
- async recommendEventDeck(eventId, musicMeta, liveType, limit = 1) {
666
+ async recommendEventDeck(eventId, liveType, config) {
640
667
  const userCards = await this.dataProvider.getUserData('userCards');
641
- const recommend = await this.baseRecommend.recommendHighScoreDeck(userCards, musicMeta, BaseDeckRecommend.getEventPointFunction(liveType), limit, eventId);
668
+ const recommend = await this.baseRecommend.recommendHighScoreDeck(userCards, BaseDeckRecommend.getEventPointFunction(liveType), config, eventId);
642
669
  return recommend.map(it => {
643
670
  return {
644
671
  point: it.score,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sekai-calculator",
3
- "version": "0.4.3",
3
+ "version": "0.5.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",
@@ -30,22 +30,22 @@
30
30
  },
31
31
  "license": "LGPL-2.1-or-later",
32
32
  "devDependencies": {
33
- "@rollup/plugin-typescript": "^11.0.0",
34
- "@types/jest": "^29.4.1",
35
- "@types/node": "^18.15.3",
36
- "@typescript-eslint/eslint-plugin": "^5.55.0",
37
- "eslint": "^8.36.0",
38
- "eslint-config-standard-with-typescript": "^34.0.0",
33
+ "@rollup/plugin-typescript": "^11.1.0",
34
+ "@types/jest": "^29.5.0",
35
+ "@types/node": "^18.15.11",
36
+ "@typescript-eslint/eslint-plugin": "^5.57.1",
37
+ "eslint": "^8.37.0",
38
+ "eslint-config-standard-with-typescript": "^34.0.1",
39
39
  "eslint-plugin-import": "^2.27.5",
40
- "eslint-plugin-n": "^15.6.1",
40
+ "eslint-plugin-n": "^15.7.0",
41
41
  "eslint-plugin-promise": "^6.1.1",
42
42
  "jest": "^29.5.0",
43
- "rollup": "^3.19.1",
44
- "rollup-plugin-dts": "^5.2.0",
45
- "ts-jest": "^29.0.5",
43
+ "rollup": "^3.20.2",
44
+ "rollup-plugin-dts": "^5.3.0",
45
+ "ts-jest": "^29.1.0",
46
46
  "ts-node": "^10.9.1",
47
47
  "tslib": "^2.5.0",
48
- "typescript": "^4.9.5"
48
+ "typescript": "^5.0.3"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "rollup -c --configPlugin typescript",