From bde080eadd1bc7fdf7f5b5678b752834543fb432 Mon Sep 17 00:00:00 2001 From: Branden J Brown Date: Thu, 13 Aug 2026 17:39:23 -0400 Subject: [PATCH] zenno: add support card level and effect functonality --- zenno/src/lib/data/support.spec.ts | 411 +++++++++++ zenno/src/lib/data/support.ts | 142 ++++ zenno/src/lib/data/support_card_level.json | 679 ++++++++++++++++++ .../testdata/support-10018-bakushin-R.json | 415 +++++++++++ .../testdata/support-20042-bakushin-SR.json | 429 +++++++++++ .../testdata/support-30083-bakushin-SSR.json | 471 ++++++++++++ zenno/src/lib/vitest-examples/Welcome.svelte | 8 - .../vitest-examples/Welcome.svelte.spec.ts | 13 - zenno/src/lib/vitest-examples/greet.spec.ts | 8 - zenno/src/lib/vitest-examples/greet.ts | 3 - 10 files changed, 2547 insertions(+), 32 deletions(-) create mode 100644 zenno/src/lib/data/support.spec.ts create mode 100644 zenno/src/lib/data/support_card_level.json create mode 100644 zenno/src/lib/data/testdata/support-10018-bakushin-R.json create mode 100644 zenno/src/lib/data/testdata/support-20042-bakushin-SR.json create mode 100644 zenno/src/lib/data/testdata/support-30083-bakushin-SSR.json delete mode 100644 zenno/src/lib/vitest-examples/Welcome.svelte delete mode 100644 zenno/src/lib/vitest-examples/Welcome.svelte.spec.ts delete mode 100644 zenno/src/lib/vitest-examples/greet.spec.ts delete mode 100644 zenno/src/lib/vitest-examples/greet.ts diff --git a/zenno/src/lib/data/support.spec.ts b/zenno/src/lib/data/support.spec.ts new file mode 100644 index 0000000..caf2a71 --- /dev/null +++ b/zenno/src/lib/data/support.spec.ts @@ -0,0 +1,411 @@ +import * as support from './support'; +import { describe, expect, test } from 'vitest'; + +import * as bakushinR from './testdata/support-10018-bakushin-R.json'; +import * as bakushinSR from './testdata/support-20042-bakushin-SR.json'; +import * as bakushinSSR from './testdata/support-30083-bakushin-SSR.json'; + +test.for([ + { rarity: support.Rarity.R, exp: 0, level: 1 }, + { rarity: support.Rarity.R, exp: 5, level: 2 }, + { rarity: support.Rarity.R, exp: 10, level: 2 }, + { rarity: support.Rarity.R, exp: 40510, level: 40 }, + { rarity: support.Rarity.SR, exp: 0, level: 1 }, + { rarity: support.Rarity.SR, exp: 10, level: 2 }, + { rarity: support.Rarity.SR, exp: 20, level: 2 }, + { rarity: support.Rarity.SR, exp: 74990, level: 45 }, + { rarity: support.Rarity.SSR, exp: 0, level: 1 }, + { rarity: support.Rarity.SSR, exp: 15, level: 2 }, + { rarity: support.Rarity.SSR, exp: 30, level: 2 }, + { rarity: support.Rarity.SSR, exp: 118185, level: 50 }, +])('level($rarity, $exp) -> $level', ({ rarity, exp, level }) => expect(support.level(rarity, exp)).toBe(level)); + +describe('effects', () => { + + describe('Bakushin R', () => { + test('level 1', () => { + const got = support.effects(bakushinR as support.SupportCard, 1); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 5 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.SpeedBonus, value: 0 }, + { type: support.EffectType.InitialSpeed, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 1 }, + { type: support.EffectType.SpecialtyPriority, value: 0 }, + ], + }); + }); + test('level 2', () => { + const got = support.effects(bakushinR as support.SupportCard, 2); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 5 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.SpeedBonus, value: 0 }, + { type: support.EffectType.InitialSpeed, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 1 }, + { type: support.EffectType.SpecialtyPriority, value: 0 }, + ], + }); + }); + test('level 5', () => { + const got = support.effects(bakushinR as support.SupportCard, 5); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 6 }, + { type: support.EffectType.MoodEffect, value: 10 }, + { type: support.EffectType.SpeedBonus, value: 0 }, + { type: support.EffectType.InitialSpeed, value: 10 }, + { type: support.EffectType.InitialFriendship, value: 10 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 2 }, + { type: support.EffectType.SpecialtyPriority, value: 5 }, + ], + }); + }); + test('level 6', () => { + const got = support.effects(bakushinR as support.SupportCard, 6); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 6 }, + { type: support.EffectType.MoodEffect, value: 10 }, + { type: support.EffectType.SpeedBonus, value: 0 }, + { type: support.EffectType.InitialSpeed, value: 10 }, + { type: support.EffectType.InitialFriendship, value: 10 }, + { type: support.EffectType.RaceBonus, value: 2 }, + { type: support.EffectType.FanBonus, value: 3 }, + { type: support.EffectType.SpecialtyPriority, value: 6 }, + ], + }); + }); + test('level 39', () => { + const got = support.effects(bakushinR as support.SupportCard, 39); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 15 }, + { type: support.EffectType.MoodEffect, value: 25 }, + { type: support.EffectType.SpeedBonus, value: 0 }, + { type: support.EffectType.InitialSpeed, value: 20 }, + { type: support.EffectType.InitialFriendship, value: 20 }, + { type: support.EffectType.RaceBonus, value: 5 }, + { type: support.EffectType.FanBonus, value: 14 }, + { type: support.EffectType.SpecialtyPriority, value: 35 }, + ], + }); + }); + test('level 40', () => { + const got = support.effects(bakushinR as support.SupportCard, 40); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 15 }, + { type: support.EffectType.MoodEffect, value: 25 }, + { type: support.EffectType.SpeedBonus, value: 1 }, + { type: support.EffectType.InitialSpeed, value: 20 }, + { type: support.EffectType.InitialFriendship, value: 20 }, + { type: support.EffectType.RaceBonus, value: 5 }, + { type: support.EffectType.FanBonus, value: 15 }, + { type: support.EffectType.SpecialtyPriority, value: 35 }, + ], + }); + }); + }); + + describe('Bakushin SR', () => { + test('level 1', () => { + const got = support.effects(bakushinSR as support.SupportCard, 1); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 10 }, + { type: support.EffectType.PowerBonus, value: 0 }, + { type: support.EffectType.TrainingEffectiveness, value: 0 }, + { type: support.EffectType.InitialPower, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 1 }, + { type: support.EffectType.SpecialtyPriority, value: 0 }, + ], + }); + }); + test('level 2', () => { + const got = support.effects(bakushinSR as support.SupportCard, 2); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 10 }, + { type: support.EffectType.PowerBonus, value: 0 }, + { type: support.EffectType.TrainingEffectiveness, value: 0 }, + { type: support.EffectType.InitialPower, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 1 }, + { type: support.EffectType.SpecialtyPriority, value: 0 }, + ], + }); + }); + test('level 5', () => { + const got = support.effects(bakushinSR as support.SupportCard, 5); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 11 }, + { type: support.EffectType.PowerBonus, value: 0 }, + { type: support.EffectType.TrainingEffectiveness, value: 0 }, + { type: support.EffectType.InitialPower, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 3 }, + { type: support.EffectType.SpecialtyPriority, value: 5 }, + ], + }); + }); + test('level 24', () => { + const got = support.effects(bakushinSR as support.SupportCard, 24); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 15 }, + { type: support.EffectType.PowerBonus, value: 0 }, + { type: support.EffectType.TrainingEffectiveness, value: 5 }, + { type: support.EffectType.InitialPower, value: 15 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 4 }, + { type: support.EffectType.FanBonus, value: 14 }, + { type: support.EffectType.SpecialtyPriority, value: 33 }, + ], + }); + }); + test('level 25', () => { + const got = support.effects(bakushinSR as support.SupportCard, 25); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 15 }, + { type: support.EffectType.PowerBonus, value: 0 }, + { type: support.EffectType.TrainingEffectiveness, value: 5 }, + { type: support.EffectType.InitialPower, value: 15 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 5 }, + { type: support.EffectType.FanBonus, value: 15 }, + { type: support.EffectType.SpecialtyPriority, value: 35 }, + ], + unique: { + name: 'The Perfect Morning Greeting!', + description: 'Friendship Bonus and Specialty Priority', + card_level: 25, + type: support.EffectType.FriendshipBonus, + args: [10], + type2: support.EffectType.SpecialtyPriority, + args2: [20], + idle_mode_sub_rate: 0, + } satisfies support.UniqueEffect, + }); + }); + test('level 44', () => { + const got = support.effects(bakushinSR as support.SupportCard, 44); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 20 }, + { type: support.EffectType.PowerBonus, value: 0 }, + { type: support.EffectType.TrainingEffectiveness, value: 5 }, + { type: support.EffectType.InitialPower, value: 20 }, + { type: support.EffectType.InitialFriendship, value: 20 }, + { type: support.EffectType.RaceBonus, value: 9 }, + { type: support.EffectType.FanBonus, value: 19 }, + { type: support.EffectType.SpecialtyPriority, value: 49 }, + ], + unique: { + name: 'The Perfect Morning Greeting!', + description: 'Friendship Bonus and Specialty Priority', + card_level: 25, + type: support.EffectType.FriendshipBonus, + args: [10], + type2: support.EffectType.SpecialtyPriority, + args2: [20], + idle_mode_sub_rate: 0, + } satisfies support.UniqueEffect, + }); + }); + test('level 45', () => { + const got = support.effects(bakushinSR as support.SupportCard, 45); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 20 }, + { type: support.EffectType.PowerBonus, value: 1 }, + { type: support.EffectType.TrainingEffectiveness, value: 5 }, + { type: support.EffectType.InitialPower, value: 20 }, + { type: support.EffectType.InitialFriendship, value: 20 }, + { type: support.EffectType.RaceBonus, value: 10 }, + { type: support.EffectType.FanBonus, value: 20 }, + { type: support.EffectType.SpecialtyPriority, value: 50 }, + ], + unique: { + name: 'The Perfect Morning Greeting!', + description: 'Friendship Bonus and Specialty Priority', + card_level: 25, + type: support.EffectType.FriendshipBonus, + args: [10], + type2: support.EffectType.SpecialtyPriority, + args2: [20], + idle_mode_sub_rate: 0, + } satisfies support.UniqueEffect, + }); + }); + }) + + describe('Bakushin SSR', () => { + test('level 1', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 1); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 10 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.GutsBonus, value: 0 }, + { type: support.EffectType.InitialGuts, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 1 }, + { type: support.EffectType.HintLevels, value: 1 }, + { type: support.EffectType.HintFrequency, value: 5 }, + ], + }); + }); + test('level 2', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 2); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 10 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.GutsBonus, value: 0 }, + { type: support.EffectType.InitialGuts, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 1 }, + { type: support.EffectType.HintLevels, value: 1 }, + { type: support.EffectType.HintFrequency, value: 6 }, + ], + }); + }); + test('level 5', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 5); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 12 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.GutsBonus, value: 0 }, + { type: support.EffectType.InitialGuts, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 0 }, + { type: support.EffectType.RaceBonus, value: 1 }, + { type: support.EffectType.FanBonus, value: 2 }, + { type: support.EffectType.HintLevels, value: 1 }, + { type: support.EffectType.HintFrequency, value: 9 }, + ], + }); + }); + test('level 10', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 10); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 14 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.GutsBonus, value: 0 }, + { type: support.EffectType.InitialGuts, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 10 }, + { type: support.EffectType.RaceBonus, value: 2 }, + { type: support.EffectType.FanBonus, value: 5 }, + { type: support.EffectType.HintLevels, value: 1 }, + { type: support.EffectType.HintFrequency, value: 15 }, + ], + }); + }); + test('level 11', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 11); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 15 }, + { type: support.EffectType.MoodEffect, value: 0 }, + { type: support.EffectType.GutsBonus, value: 0 }, + { type: support.EffectType.InitialGuts, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 10 }, + { type: support.EffectType.RaceBonus, value: 2 }, + { type: support.EffectType.FanBonus, value: 5 }, + { type: support.EffectType.HintLevels, value: 1 }, + { type: support.EffectType.HintFrequency, value: 17 }, + ], + }); + }); + test('level 30', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 30); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 25 }, + { type: support.EffectType.MoodEffect, value: 20 }, + { type: support.EffectType.GutsBonus, value: 0 }, + { type: support.EffectType.InitialGuts, value: 0 }, + { type: support.EffectType.InitialFriendship, value: 20 }, + { type: support.EffectType.RaceBonus, value: 5 }, + { type: support.EffectType.FanBonus, value: 15 }, + { type: support.EffectType.HintLevels, value: 2 }, + { type: support.EffectType.HintFrequency, value: 40 }, + ], + unique: { + name: 'Super! Sonic! Flower Power!', + description: 'Increases Training Effectiveness when not on preferred training. (Friendship 80+)', + card_level: 30, + type: support.EffectType.UniqueOffSpecialty, + args: [80, 20], + idle_mode_sub_rate: 30, + } satisfies support.UniqueEffect, + }); + }); + test('level 49', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 49); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 34 }, + { type: support.EffectType.MoodEffect, value: 30 }, + { type: support.EffectType.GutsBonus, value: 1 }, + { type: support.EffectType.InitialGuts, value: 27 }, + { type: support.EffectType.InitialFriendship, value: 25 }, + { type: support.EffectType.RaceBonus, value: 9 }, + { type: support.EffectType.FanBonus, value: 19 }, + { type: support.EffectType.HintLevels, value: 2 }, + { type: support.EffectType.HintFrequency, value: 49 }, + ], + unique: { + name: 'Super! Sonic! Flower Power!', + description: 'Increases Training Effectiveness when not on preferred training. (Friendship 80+)', + card_level: 30, + type: support.EffectType.UniqueOffSpecialty, + args: [80, 20], + idle_mode_sub_rate: 30, + } satisfies support.UniqueEffect, + }); + }); + test('level 50', () => { + const got = support.effects(bakushinSSR as support.SupportCard, 50); + expect(got).toStrictEqual({ + effects: [ + { type: support.EffectType.FriendshipBonus, value: 35 }, + { type: support.EffectType.MoodEffect, value: 30 }, + { type: support.EffectType.GutsBonus, value: 1 }, + { type: support.EffectType.InitialGuts, value: 30 }, + { type: support.EffectType.InitialFriendship, value: 25 }, + { type: support.EffectType.RaceBonus, value: 10 }, + { type: support.EffectType.FanBonus, value: 20 }, + { type: support.EffectType.HintLevels, value: 3 }, + { type: support.EffectType.HintFrequency, value: 50 }, + ], + unique: { + name: 'Super! Sonic! Flower Power!', + description: 'Increases Training Effectiveness when not on preferred training. (Friendship 80+)', + card_level: 30, + type: support.EffectType.UniqueOffSpecialty, + args: [80, 20], + idle_mode_sub_rate: 30, + } satisfies support.UniqueEffect, + }); + }); + }); + +}); \ No newline at end of file diff --git a/zenno/src/lib/data/support.ts b/zenno/src/lib/data/support.ts index b709b68..325ffea 100644 --- a/zenno/src/lib/data/support.ts +++ b/zenno/src/lib/data/support.ts @@ -1,3 +1,5 @@ +import * as support_card_level from './support_card_level.json'; + /** * Support card definitions. */ @@ -224,3 +226,143 @@ export const SPECIALTY_ICON = { Pal: 5, Group: 6, } as const; + +/** + * Compute the current effects of a support card at a given level. + * @param card Support card to compute current effects for. + * @param level Experience level of the support card. + * @returns Current support card effects and its unique effect if active at the given level. + */ +export function effects(card: SupportCard, level: number) { + const j = Math.floor(level / 5); + const k = Math.ceil(level / 5); + const effects = card.effects[0].map((e) => { + const s = card.effects.map((l) => l.find((f) => f.type === e.type)!); + const left = s.findLastIndex((f, i) => i <= j && f.value >= 0); + const right = s.findIndex((f, i) => k <= i && f.value >= 0); + if (left < 0) { + // Effect isn't yet active. + return { type: e.type, value: 0 }; + } + if (right < 0) { + // Effect is at its maximum value. + return { type: e.type, value: s[left]!.value }; + } + if (left === right) { + // The current level is an interpolation boundary. + // Don't try to interpolate. + return { type: e.type, value: s[left]!.value }; + } + const xl = Math.max(left * 5, 1); + const xr = Math.max(right * 5, 1); + const lo = s[left]!.value; + const hi = s[right]!.value; + const value = Math.floor((hi * (level - xl) + lo * (xr - level)) / (xr - xl)); + return { type: e.type, value }; + }); + if (card.unique_effect != null && level >= card.unique_effect.card_level) { + return { effects, unique: card.unique_effect } + } + return { effects }; +} + +export function level(rarity: Rarity, exp: number) { + // We use the ! assertion because we want an error when exp is nonsense. + return support_card_level.levels.findLast((l) => l.rarity === rarity && l.exp <= exp)!.level; +} + +function singleUniqueEffects(type: EffectType, args: number[], deck: SupportCard[]): Effect[] { + switch (type) { + case EffectType.FriendshipBonus: + case EffectType.MoodEffect: + case EffectType.SpeedBonus: + case EffectType.StaminaBonus: + case EffectType.PowerBonus: + case EffectType.GutsBonus: + case EffectType.WitBonus: + case EffectType.TrainingEffectiveness: + case EffectType.InitialSpeed: + case EffectType.InitialStamina: + case EffectType.InitialPower: + case EffectType.InitialGuts: + case EffectType.InitialWit: + case EffectType.InitialFriendship: + case EffectType.RaceBonus: + case EffectType.FanBonus: + case EffectType.HintLevels: + case EffectType.HintFrequency: + case EffectType.SpecialtyPriority: + case EffectType.MaxSpeed: + case EffectType.MaxStamina: + case EffectType.MaxPower: + case EffectType.MaxGuts: + case EffectType.MaxWit: + case EffectType.EventRecovery: + case EffectType.EventEffectiveness: + case EffectType.FailureProtection: + case EffectType.EnergyCostReduction: + case EffectType.MinigameEffectiveness: + case EffectType.SkillPointBonus: + case EffectType.WitFriendshipRecovery: + return [{ type, value: args[0] }]; + + case EffectType.UniqueFriendshipThreshold: + return [{ type: args[1], value: args[2] }, { type: args[3], value: args[4] }]; + case EffectType.UniqueOffSpecialty: + return [{ type: EffectType.TrainingEffectiveness, value: args[1] }]; + case EffectType.UniqueColorThresholdTrainingEffectiveness: + if (new Set(deck.map((card) => card.specialty)).size < args[0]) { + return []; + } + return [{ type: EffectType.TrainingEffectiveness, value: args[1] }]; + case EffectType.UniqueFanScalingTrainingEffectiveness: + return [{ type: EffectType.TrainingEffectiveness, value: args[1] }] + case EffectType.UniqueColorInitialStats: + return deck.flatMap((card) => { + switch (card.specialty) { + case Specialty.Speed: + return [{ type: EffectType.InitialSpeed, value: args[0] }]; + case Specialty.Power: + return [{ type: EffectType.InitialPower, value: args[0] }]; + case Specialty.Guts: + return [{ type: EffectType.InitialGuts, value: args[0] }]; + case Specialty.Stamina: + return [{ type: EffectType.InitialStamina, value: args[0] }]; + case Specialty.Wit: + return [{ type: EffectType.InitialWit, value: args[0] }]; + default: + return [ + { type: EffectType.InitialSpeed, value: args[1] }, + { type: EffectType.InitialStamina, value: args[1] }, + { type: EffectType.InitialPower, value: args[1] }, + { type: EffectType.InitialGuts, value: args[1] }, + { type: EffectType.InitialWit, value: args[1] }, + ]; + } + }) + case EffectType.UniqueRainbowStack: + return [{ type: args[1], value: args[0] * args[2] }]; + case EffectType.UniqueLowEnergyScaling: + return [{ type: args[0], value: args[3] }]; + case EffectType.UniqueMaxEnergyScaling: + return [{ type: args[0], value: args[4] }]; + case EffectType.UniqueTotalFriendship: + return [{ type: args[0], value: 600 / args[1] }]; + case EffectType.UniqueCardCount: + return [{ type: args[0], value: 5 * args[1] }]; + case EffectType.UniqueFacilityLevel: + return [{ type: args[0], value: 5 * args[1] }]; + case EffectType.UniqueDisableFailure: + return []; + case EffectType.UniqueFriendshipTrainingAdditionalEffect: + return [{ type: args[0], value: args[1] }]; + } +} + +export function flattenUnique(unique: UniqueEffect, deck: SupportCard[]): Effect[] { + const r = [...singleUniqueEffects(unique.type, unique.args, deck)]; + if (unique.type2 != null) { + r.push(...singleUniqueEffects(unique.type2, unique.args2!, deck)); + } + return r; +} diff --git a/zenno/src/lib/data/support_card_level.json b/zenno/src/lib/data/support_card_level.json new file mode 100644 index 0000000..d7562ac --- /dev/null +++ b/zenno/src/lib/data/support_card_level.json @@ -0,0 +1,679 @@ +{ + "levels": [ + { + "rarity": 1, + "exp": 0, + "level": 1 + }, + { + "rarity": 1, + "exp": 5, + "level": 2 + }, + { + "rarity": 1, + "exp": 15, + "level": 3 + }, + { + "rarity": 1, + "exp": 30, + "level": 4 + }, + { + "rarity": 1, + "exp": 50, + "level": 5 + }, + { + "rarity": 1, + "exp": 80, + "level": 6 + }, + { + "rarity": 1, + "exp": 120, + "level": 7 + }, + { + "rarity": 1, + "exp": 170, + "level": 8 + }, + { + "rarity": 1, + "exp": 230, + "level": 9 + }, + { + "rarity": 1, + "exp": 310, + "level": 10 + }, + { + "rarity": 1, + "exp": 410, + "level": 11 + }, + { + "rarity": 1, + "exp": 530, + "level": 12 + }, + { + "rarity": 1, + "exp": 680, + "level": 13 + }, + { + "rarity": 1, + "exp": 860, + "level": 14 + }, + { + "rarity": 1, + "exp": 1080, + "level": 15 + }, + { + "rarity": 1, + "exp": 1340, + "level": 16 + }, + { + "rarity": 1, + "exp": 1650, + "level": 17 + }, + { + "rarity": 1, + "exp": 2010, + "level": 18 + }, + { + "rarity": 1, + "exp": 2430, + "level": 19 + }, + { + "rarity": 1, + "exp": 2910, + "level": 20 + }, + { + "rarity": 1, + "exp": 3460, + "level": 21 + }, + { + "rarity": 1, + "exp": 4090, + "level": 22 + }, + { + "rarity": 1, + "exp": 4810, + "level": 23 + }, + { + "rarity": 1, + "exp": 5630, + "level": 24 + }, + { + "rarity": 1, + "exp": 6560, + "level": 25 + }, + { + "rarity": 1, + "exp": 7610, + "level": 26 + }, + { + "rarity": 1, + "exp": 8790, + "level": 27 + }, + { + "rarity": 1, + "exp": 10110, + "level": 28 + }, + { + "rarity": 1, + "exp": 11580, + "level": 29 + }, + { + "rarity": 1, + "exp": 13210, + "level": 30 + }, + { + "rarity": 1, + "exp": 15010, + "level": 31 + }, + { + "rarity": 1, + "exp": 16990, + "level": 32 + }, + { + "rarity": 1, + "exp": 19160, + "level": 33 + }, + { + "rarity": 1, + "exp": 21530, + "level": 34 + }, + { + "rarity": 1, + "exp": 24110, + "level": 35 + }, + { + "rarity": 1, + "exp": 26910, + "level": 36 + }, + { + "rarity": 1, + "exp": 29940, + "level": 37 + }, + { + "rarity": 1, + "exp": 33210, + "level": 38 + }, + { + "rarity": 1, + "exp": 36730, + "level": 39 + }, + { + "rarity": 1, + "exp": 40510, + "level": 40 + }, + { + "rarity": 2, + "exp": 0, + "level": 1 + }, + { + "rarity": 2, + "exp": 10, + "level": 2 + }, + { + "rarity": 2, + "exp": 30, + "level": 3 + }, + { + "rarity": 2, + "exp": 60, + "level": 4 + }, + { + "rarity": 2, + "exp": 110, + "level": 5 + }, + { + "rarity": 2, + "exp": 180, + "level": 6 + }, + { + "rarity": 2, + "exp": 270, + "level": 7 + }, + { + "rarity": 2, + "exp": 390, + "level": 8 + }, + { + "rarity": 2, + "exp": 540, + "level": 9 + }, + { + "rarity": 2, + "exp": 720, + "level": 10 + }, + { + "rarity": 2, + "exp": 940, + "level": 11 + }, + { + "rarity": 2, + "exp": 1200, + "level": 12 + }, + { + "rarity": 2, + "exp": 1510, + "level": 13 + }, + { + "rarity": 2, + "exp": 1870, + "level": 14 + }, + { + "rarity": 2, + "exp": 2290, + "level": 15 + }, + { + "rarity": 2, + "exp": 2770, + "level": 16 + }, + { + "rarity": 2, + "exp": 3320, + "level": 17 + }, + { + "rarity": 2, + "exp": 3940, + "level": 18 + }, + { + "rarity": 2, + "exp": 4640, + "level": 19 + }, + { + "rarity": 2, + "exp": 5420, + "level": 20 + }, + { + "rarity": 2, + "exp": 6290, + "level": 21 + }, + { + "rarity": 2, + "exp": 7250, + "level": 22 + }, + { + "rarity": 2, + "exp": 8310, + "level": 23 + }, + { + "rarity": 2, + "exp": 9470, + "level": 24 + }, + { + "rarity": 2, + "exp": 10740, + "level": 25 + }, + { + "rarity": 2, + "exp": 12130, + "level": 26 + }, + { + "rarity": 2, + "exp": 13650, + "level": 27 + }, + { + "rarity": 2, + "exp": 15310, + "level": 28 + }, + { + "rarity": 2, + "exp": 17120, + "level": 29 + }, + { + "rarity": 2, + "exp": 19090, + "level": 30 + }, + { + "rarity": 2, + "exp": 21230, + "level": 31 + }, + { + "rarity": 2, + "exp": 23550, + "level": 32 + }, + { + "rarity": 2, + "exp": 26060, + "level": 33 + }, + { + "rarity": 2, + "exp": 28770, + "level": 34 + }, + { + "rarity": 2, + "exp": 31690, + "level": 35 + }, + { + "rarity": 2, + "exp": 34830, + "level": 36 + }, + { + "rarity": 2, + "exp": 38200, + "level": 37 + }, + { + "rarity": 2, + "exp": 41810, + "level": 38 + }, + { + "rarity": 2, + "exp": 45670, + "level": 39 + }, + { + "rarity": 2, + "exp": 49790, + "level": 40 + }, + { + "rarity": 2, + "exp": 54190, + "level": 41 + }, + { + "rarity": 2, + "exp": 58890, + "level": 42 + }, + { + "rarity": 2, + "exp": 63910, + "level": 43 + }, + { + "rarity": 2, + "exp": 69270, + "level": 44 + }, + { + "rarity": 2, + "exp": 74990, + "level": 45 + }, + { + "rarity": 3, + "exp": 0, + "level": 1 + }, + { + "rarity": 3, + "exp": 15, + "level": 2 + }, + { + "rarity": 3, + "exp": 45, + "level": 3 + }, + { + "rarity": 3, + "exp": 95, + "level": 4 + }, + { + "rarity": 3, + "exp": 165, + "level": 5 + }, + { + "rarity": 3, + "exp": 265, + "level": 6 + }, + { + "rarity": 3, + "exp": 395, + "level": 7 + }, + { + "rarity": 3, + "exp": 565, + "level": 8 + }, + { + "rarity": 3, + "exp": 775, + "level": 9 + }, + { + "rarity": 3, + "exp": 1035, + "level": 10 + }, + { + "rarity": 3, + "exp": 1345, + "level": 11 + }, + { + "rarity": 3, + "exp": 1715, + "level": 12 + }, + { + "rarity": 3, + "exp": 2145, + "level": 13 + }, + { + "rarity": 3, + "exp": 2645, + "level": 14 + }, + { + "rarity": 3, + "exp": 3215, + "level": 15 + }, + { + "rarity": 3, + "exp": 3865, + "level": 16 + }, + { + "rarity": 3, + "exp": 4595, + "level": 17 + }, + { + "rarity": 3, + "exp": 5415, + "level": 18 + }, + { + "rarity": 3, + "exp": 6325, + "level": 19 + }, + { + "rarity": 3, + "exp": 7335, + "level": 20 + }, + { + "rarity": 3, + "exp": 8445, + "level": 21 + }, + { + "rarity": 3, + "exp": 9665, + "level": 22 + }, + { + "rarity": 3, + "exp": 10995, + "level": 23 + }, + { + "rarity": 3, + "exp": 12445, + "level": 24 + }, + { + "rarity": 3, + "exp": 14015, + "level": 25 + }, + { + "rarity": 3, + "exp": 15715, + "level": 26 + }, + { + "rarity": 3, + "exp": 17545, + "level": 27 + }, + { + "rarity": 3, + "exp": 19515, + "level": 28 + }, + { + "rarity": 3, + "exp": 21625, + "level": 29 + }, + { + "rarity": 3, + "exp": 23885, + "level": 30 + }, + { + "rarity": 3, + "exp": 26305, + "level": 31 + }, + { + "rarity": 3, + "exp": 28895, + "level": 32 + }, + { + "rarity": 3, + "exp": 31665, + "level": 33 + }, + { + "rarity": 3, + "exp": 34625, + "level": 34 + }, + { + "rarity": 3, + "exp": 37785, + "level": 35 + }, + { + "rarity": 3, + "exp": 41155, + "level": 36 + }, + { + "rarity": 3, + "exp": 44745, + "level": 37 + }, + { + "rarity": 3, + "exp": 48565, + "level": 38 + }, + { + "rarity": 3, + "exp": 52625, + "level": 39 + }, + { + "rarity": 3, + "exp": 56935, + "level": 40 + }, + { + "rarity": 3, + "exp": 61515, + "level": 41 + }, + { + "rarity": 3, + "exp": 66385, + "level": 42 + }, + { + "rarity": 3, + "exp": 71565, + "level": 43 + }, + { + "rarity": 3, + "exp": 77075, + "level": 44 + }, + { + "rarity": 3, + "exp": 82935, + "level": 45 + }, + { + "rarity": 3, + "exp": 89165, + "level": 46 + }, + { + "rarity": 3, + "exp": 95785, + "level": 47 + }, + { + "rarity": 3, + "exp": 102815, + "level": 48 + }, + { + "rarity": 3, + "exp": 110275, + "level": 49 + }, + { + "rarity": 3, + "exp": 118185, + "level": 50 + } + ] +} \ No newline at end of file diff --git a/zenno/src/lib/data/testdata/support-10018-bakushin-R.json b/zenno/src/lib/data/testdata/support-10018-bakushin-R.json new file mode 100644 index 0000000..e0add49 --- /dev/null +++ b/zenno/src/lib/data/testdata/support-10018-bakushin-R.json @@ -0,0 +1,415 @@ +{ + "id": 10018, + "name": "[Tracen Academy] Sakura Bakushin O", + "chara_id": 1041, + "chara_name": "Sakura Bakushin O", + "rarity": 1, + "specialty": 101, + "type": 1, + "effects": [ + [ + { + "type": 1, + "value": 5 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 1 + }, + { + "type": 16, + "value": 1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": 10 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": 10 + }, + { + "type": 14, + "value": 10 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": 5 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 10 + }, + { + "type": 2, + "value": 15 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": 15 + }, + { + "type": 14, + "value": 15 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": 20 + } + ], + [ + { + "type": 1, + "value": 10 + }, + { + "type": 2, + "value": 15 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": 15 + }, + { + "type": 14, + "value": 15 + }, + { + "type": 15, + "value": 5 + }, + { + "type": 16, + "value": 10 + }, + { + "type": 19, + "value": 20 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 15 + }, + { + "type": 2, + "value": 25 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": 20 + }, + { + "type": 14, + "value": 20 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": 35 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": 1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 5 + }, + { + "type": 16, + "value": 15 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 3, + "value": -1 + }, + { + "type": 9, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ] + ], + "hints": [ + { + "skill_id": 200652 + }, + { + "skill_id": 200791 + }, + { + "skill_id": 200841 + }, + { + "skill_id": 200962 + }, + { + "skill_id": 200972 + }, + { + "skill_id": 200982 + }, + { + "skill_id": 200992 + }, + { + "skill_id": 201012 + }, + { + "speed": 6, + "power": 2 + } + ] +} diff --git a/zenno/src/lib/data/testdata/support-20042-bakushin-SR.json b/zenno/src/lib/data/testdata/support-20042-bakushin-SR.json new file mode 100644 index 0000000..8c0f064 --- /dev/null +++ b/zenno/src/lib/data/testdata/support-20042-bakushin-SR.json @@ -0,0 +1,429 @@ +{ + "id": 20042, + "name": "[The Perfect Morning Greeting!] Sakura Bakushin O", + "chara_id": 1041, + "chara_name": "Sakura Bakushin O", + "rarity": 2, + "specialty": 102, + "type": 1, + "effects": [ + [ + { + "type": 1, + "value": 10 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 1 + }, + { + "type": 16, + "value": 1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": 5 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": 1 + }, + { + "type": 11, + "value": 10 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 15 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": 5 + }, + { + "type": 11, + "value": 15 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 15 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": 5 + }, + { + "type": 11, + "value": 15 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 5 + }, + { + "type": 16, + "value": 15 + }, + { + "type": 19, + "value": 35 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": 10 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 20 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": 5 + }, + { + "type": 11, + "value": 20 + }, + { + "type": 14, + "value": 20 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": 1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 10 + }, + { + "type": 16, + "value": 20 + }, + { + "type": 19, + "value": 50 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 5, + "value": -1 + }, + { + "type": 8, + "value": -1 + }, + { + "type": 11, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 19, + "value": -1 + } + ] + ], + "unique_effect": { + "name": "The Perfect Morning Greeting!", + "description": "Friendship Bonus and Specialty Priority", + "card_level": 25, + "type": 1, + "args": [ + 10 + ], + "type2": 19, + "args2": [ + 20 + ], + "idle_mode_sub_rate": 0 + }, + "hints": [ + { + "skill_id": 200652 + }, + { + "skill_id": 200791 + }, + { + "skill_id": 200841 + }, + { + "skill_id": 200962 + }, + { + "skill_id": 200972 + }, + { + "skill_id": 200982 + }, + { + "skill_id": 200992 + }, + { + "skill_id": 201012 + }, + { + "stamina": 2, + "power": 6 + } + ] +} diff --git a/zenno/src/lib/data/testdata/support-30083-bakushin-SSR.json b/zenno/src/lib/data/testdata/support-30083-bakushin-SSR.json new file mode 100644 index 0000000..c7963b3 --- /dev/null +++ b/zenno/src/lib/data/testdata/support-30083-bakushin-SSR.json @@ -0,0 +1,471 @@ +{ + "id": 30083, + "name": "[Super! Sonic! Flower Power!] Sakura Bakushin O", + "chara_id": 1041, + "chara_name": "Sakura Bakushin O", + "rarity": 3, + "specialty": 103, + "type": 1, + "effects": [ + [ + { + "type": 1, + "value": 10 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 1 + }, + { + "type": 16, + "value": 1 + }, + { + "type": 17, + "value": 1 + }, + { + "type": 18, + "value": 5 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": 10 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": 10 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": 20 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": 20 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 25 + }, + { + "type": 2, + "value": 20 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": 20 + }, + { + "type": 15, + "value": 5 + }, + { + "type": 16, + "value": 15 + }, + { + "type": 17, + "value": 2 + }, + { + "type": 18, + "value": 40 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": 1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": -1 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": -1 + }, + { + "type": 2, + "value": 30 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": 15 + }, + { + "type": 14, + "value": 25 + }, + { + "type": 15, + "value": -1 + }, + { + "type": 16, + "value": -1 + }, + { + "type": 17, + "value": -1 + }, + { + "type": 18, + "value": -1 + } + ], + [ + { + "type": 1, + "value": 35 + }, + { + "type": 2, + "value": -1 + }, + { + "type": 6, + "value": -1 + }, + { + "type": 12, + "value": 30 + }, + { + "type": 14, + "value": -1 + }, + { + "type": 15, + "value": 10 + }, + { + "type": 16, + "value": 20 + }, + { + "type": 17, + "value": 3 + }, + { + "type": 18, + "value": 50 + } + ] + ], + "unique_effect": { + "name": "Super! Sonic! Flower Power!", + "description": "Increases Training Effectiveness when not on preferred training. (Friendship 80+)", + "card_level": 30, + "type": 102, + "args": [ + 80, + 20 + ], + "idle_mode_sub_rate": 30 + }, + "hints": [ + { + "skill_id": 200652 + }, + { + "skill_id": 200791 + }, + { + "skill_id": 200841 + }, + { + "skill_id": 200962 + }, + { + "skill_id": 200972 + }, + { + "skill_id": 200982 + }, + { + "skill_id": 200992 + }, + { + "skill_id": 201012 + }, + { + "speed": 1, + "power": 1, + "guts": 6 + } + ] +} diff --git a/zenno/src/lib/vitest-examples/Welcome.svelte b/zenno/src/lib/vitest-examples/Welcome.svelte deleted file mode 100644 index c7b8460..0000000 --- a/zenno/src/lib/vitest-examples/Welcome.svelte +++ /dev/null @@ -1,8 +0,0 @@ - - -

{greet(host)}

-

{greet(guest)}

diff --git a/zenno/src/lib/vitest-examples/Welcome.svelte.spec.ts b/zenno/src/lib/vitest-examples/Welcome.svelte.spec.ts deleted file mode 100644 index 4c9a61b..0000000 --- a/zenno/src/lib/vitest-examples/Welcome.svelte.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { page } from 'vitest/browser'; -import { describe, expect, it } from 'vitest'; -import { render } from 'vitest-browser-svelte'; -import Welcome from './Welcome.svelte'; - -describe('Welcome.svelte', () => { - it('renders greetings for host and guest', async () => { - render(Welcome, { host: 'SvelteKit', guest: 'Vitest' }); - - await expect.element(page.getByRole('heading', { level: 1 })).toHaveTextContent('Hello, SvelteKit!'); - await expect.element(page.getByText('Hello, Vitest!')).toBeInTheDocument(); - }); -}); diff --git a/zenno/src/lib/vitest-examples/greet.spec.ts b/zenno/src/lib/vitest-examples/greet.spec.ts deleted file mode 100644 index f2d6b12..0000000 --- a/zenno/src/lib/vitest-examples/greet.spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { greet } from './greet'; - -describe('greet', () => { - it('returns a greeting', () => { - expect(greet('Svelte')).toBe('Hello, Svelte!'); - }); -}); diff --git a/zenno/src/lib/vitest-examples/greet.ts b/zenno/src/lib/vitest-examples/greet.ts deleted file mode 100644 index 304b482..0000000 --- a/zenno/src/lib/vitest-examples/greet.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function greet(name: string): string { - return 'Hello, ' + name + '!'; -}