diff --git a/src/commands/gegenstand.ts b/src/commands/gegenstand.ts index 20d41fe5..c4e33bdb 100644 --- a/src/commands/gegenstand.ts +++ b/src/commands/gegenstand.ts @@ -23,7 +23,7 @@ import { ensureChatInputCommand } from "#utils/interactionUtils.ts"; import * as imageService from "#service/image.ts"; import * as lootDataService from "#service/lootData.ts"; -import { LootAttributeKindId, LootKindId } from "#service/lootData.ts"; +import { LootAttributeKind, LootKind } from "#service/lootData.ts"; import log from "#log"; @@ -156,7 +156,7 @@ export default class GegenstandCommand implements ApplicationCommand { const wasteContents = await lootService.getUserLootsByTypeId( interaction.user.id, - LootKindId.RADIOACTIVE_WASTE, + LootKind.RADIOACTIVE_WASTE, ); if (wasteContents.length === 0) { @@ -168,7 +168,7 @@ export default class GegenstandCommand implements ApplicationCommand { const sweetContent = await lootService.getUserLootsWithAttribute( interaction.user.id, - LootAttributeKindId.SWEET, + LootAttributeKind.SWEET, ); if (sweetContent.length === 0) { @@ -222,7 +222,7 @@ export default class GegenstandCommand implements ApplicationCommand { const rarity = lootDataService.extractRarityAttribute(attributes) ?? - lootDataService.lootAttributeTemplates[LootAttributeKindId.RARITY_NORMAL]; + lootDataService.lootAttributeTemplates[LootAttributeKind.RARITY_NORMAL]; const otherAttributes = lootDataService.extractNonRarityAttributes(attributes); @@ -233,8 +233,7 @@ export default class GegenstandCommand implements ApplicationCommand { let assetPath = template.asset; if (template.attributeAsset) { for (const attribute of otherAttributes) { - const asset = - template.attributeAsset[attribute.attributeKindId as LootAttributeKindId]; + const asset = template.attributeAsset[attribute.attributeKindId]; if (asset) { assetPath = asset; break; @@ -265,7 +264,7 @@ export default class GegenstandCommand implements ApplicationCommand { const nutriScoreColor = lootDataService.getAttributesByClass( otherAttributes, - lootDataService.LootAttributeClassId.NUTRI_SCORE, + lootDataService.LootAttributeClass.NUTRI_SCORE, )[0]?.color; await interaction.reply({ diff --git a/src/commands/inventar.ts b/src/commands/inventar.ts index e017fef5..95b55274 100644 --- a/src/commands/inventar.ts +++ b/src/commands/inventar.ts @@ -12,7 +12,7 @@ import type { ApplicationCommand } from "#commands/command.ts"; import * as lootService from "#service/loot.ts"; import { ensureChatInputCommand } from "#utils/interactionUtils.ts"; import * as lootDataService from "#service/lootData.ts"; -import { LootAttributeKindId } from "#service/lootData.ts"; +import { LootAttributeKind } from "#service/lootData.ts"; import log from "#log"; @@ -58,7 +58,7 @@ export default class InventarCommand implements ApplicationCommand { const rarityAttribute = lootDataService.extractRarityAttribute(item.attributes); const rarity = rarityAttribute && - rarityAttribute.attributeKindId !== LootAttributeKindId.RARITY_NORMAL + rarityAttribute.attributeKindId !== LootAttributeKind.RARITY_NORMAL ? ` (${rarityAttribute.displayName})` : ""; diff --git a/src/service/birthday.ts b/src/service/birthday.ts index 6d78c78b..404c2075 100644 --- a/src/service/birthday.ts +++ b/src/service/birthday.ts @@ -103,7 +103,7 @@ ${userString} ${gotPresents ? "Zum Geurtstag habt ihr ein Geschenk erhalten" : " } async function awardBirthdayPresents(users: GuildMember[]) { - const present = lootDataService.resolveLootTemplate(lootDataService.LootKindId.GESCHENK); + const present = lootDataService.resolveLootTemplate(lootDataService.LootKind.GESCHENK); if (!present) { throw new Error("Could not resolve loot template"); } @@ -115,9 +115,7 @@ async function awardBirthdayPresents(users: GuildMember[]) { null, "birthday", null, - lootDataService.lootAttributeTemplates[ - lootDataService.LootAttributeKindId.RARITY_NORMAL - ], + lootDataService.lootAttributeTemplates[lootDataService.LootAttributeKind.RARITY_NORMAL], ); } } diff --git a/src/service/hatching.ts b/src/service/hatching.ts index d106f750..e3e9905b 100644 --- a/src/service/hatching.ts +++ b/src/service/hatching.ts @@ -7,7 +7,7 @@ import type { Loot } from "#storage/db/model.ts"; import log from "#log"; import * as time from "#utils/time.ts"; import * as lootService from "#service/loot.ts"; -import { LootKindId, resolveLootTemplate } from "./lootData.ts"; +import { LootKind, resolveLootTemplate } from "./lootData.ts"; import * as randomService from "./random.ts"; export async function hatchEggs(context: BotContext) { @@ -15,7 +15,7 @@ export async function hatchEggs(context: BotContext) { const now = Date.now(); const maxEggAge = time.days(30); - const eggs = await lootService.getLootsByKindId(LootKindId.EI); + const eggs = await lootService.getLootsByKindId(LootKind.EI); for (const e of eggs) { const itemAge = now - new Date(e.claimedAt).getTime(); @@ -34,15 +34,15 @@ export async function hatchEggs(context: BotContext) { } async function hatchEgg(context: BotContext, egg: Loot) { - console.assert(egg.lootKindId === LootKindId.EI, "Can only hatch eggs"); + console.assert(egg.lootKindId === LootKind.EI, "Can only hatch eggs"); const hatchCandidates = [ - LootKindId.KADSE, - LootKindId.BIBER, - LootKindId.FERRIS, - LootKindId.OETTINGER, - LootKindId.THUNFISCHSHAKE, - LootKindId.EI, + LootKind.KADSE, + LootKind.BIBER, + LootKind.FERRIS, + LootKind.OETTINGER, + LootKind.THUNFISCHSHAKE, + LootKind.EI, ]; const hatchWeights = [10, 10, 10, 1, 1, 5]; diff --git a/src/service/loot.ts b/src/service/loot.ts index d875416d..a9dc17ca 100644 --- a/src/service/loot.ts +++ b/src/service/loot.ts @@ -32,7 +32,10 @@ export async function getLootAttributes(id: LootId) { return await loot.getLootAttributes(id); } -export async function getUserLootCountById(userId: Snowflake, lootTypeId: number): Promise { +export async function getUserLootCountById( + userId: Snowflake, + lootTypeId: LootKindId, +): Promise { return (await loot.getUserLootsByTypeId(userId, lootTypeId)).length; } diff --git a/src/service/lootData.ts b/src/service/lootData.ts index 78a794f5..0df0f28c 100644 --- a/src/service/lootData.ts +++ b/src/service/lootData.ts @@ -9,82 +9,85 @@ import type { Loot, LootAttribute } from "#storage/db/model.ts"; const ACHTUNG_NICHT_DROPBAR_WEIGHT_KG = 0; -export enum LootKindId { - NICHTS = 0, - KADSE = 1, - MESSERBLOCK = 2, - KUEHLSCHRANK = 3, - DOENER = 4, - KINN = 5, - KRANKSCHREIBUNG = 6, - WUERFELWURF = 7, - GESCHENK = 8, - AYRAN = 9, - PKV = 10, - TRICHTER = 11, - GRAFIKKARTE = 12, - HAENDEDRUCK = 13, - ERLEUCHTUNG = 14, - BAN = 15, - OETTINGER = 16, - ACHIEVEMENT = 17, - GME_AKTIE = 18, - FERRIS = 19, - HOMEPOD = 20, - RADIOACTIVE_WASTE = 21, - SAHNE = 22, - AEHRE = 23, - CROWDSTRIKE = 24, - POWERADE_BLAU = 25, - GAULOISES_BLAU = 26, - MAXWELL = 27, - SCHICHTBEGINN_ASSE_2 = 28, - DRECK = 29, - EI = 30, - BRAVO = 31, - VERSCHIMMELTER_DOENER = 32, - THUNFISCHSHAKE = 33, - KAFFEEMUEHLE = 34, - AWS_RECHNUNG = 35, - BIBER = 36, - BLEI = 37, - USV = 38, - BAHNCARD_25 = 39, - BAHNCARD_50 = 40, - BAHNCARD_100 = 41, - LABUBU = 42, - BABYBEL_ORIGINAL = 43, - BABYBEL_LIGHT = 44, - BABYBEL_CHEDDAR = 45, - BABYBEL_EMMENTALER = 46, - BABYBEL_PROTEIN = 47, - BABYBEL_GOUDA = 48, - BABYBEL_VEGAN = 49, - BABYBEL_EXODIA = 50, -} +export const LootKind = Object.freeze({ + NICHTS: 0, + KADSE: 1, + MESSERBLOCK: 2, + KUEHLSCHRANK: 3, + DOENER: 4, + KINN: 5, + KRANKSCHREIBUNG: 6, + WUERFELWURF: 7, + GESCHENK: 8, + AYRAN: 9, + PKV: 10, + TRICHTER: 11, + GRAFIKKARTE: 12, + HAENDEDRUCK: 13, + ERLEUCHTUNG: 14, + BAN: 15, + OETTINGER: 16, + ACHIEVEMENT: 17, + GME_AKTIE: 18, + FERRIS: 19, + HOMEPOD: 20, + RADIOACTIVE_WASTE: 21, + SAHNE: 22, + AEHRE: 23, + CROWDSTRIKE: 24, + POWERADE_BLAU: 25, + GAULOISES_BLAU: 26, + MAXWELL: 27, + SCHICHTBEGINN_ASSE_2: 28, + DRECK: 29, + EI: 30, + BRAVO: 31, + VERSCHIMMELTER_DOENER: 32, + THUNFISCHSHAKE: 33, + KAFFEEMUEHLE: 34, + AWS_RECHNUNG: 35, + BIBER: 36, + BLEI: 37, + USV: 38, + BAHNCARD_25: 39, + BAHNCARD_50: 40, + BAHNCARD_100: 41, + LABUBU: 42, + BABYBEL_ORIGINAL: 43, + BABYBEL_LIGHT: 44, + BABYBEL_CHEDDAR: 45, + BABYBEL_EMMENTALER: 46, + BABYBEL_PROTEIN: 47, + BABYBEL_GOUDA: 48, + BABYBEL_VEGAN: 49, + BABYBEL_EXODIA: 50, +} as const); +export type LootKindId = (typeof LootKind)[keyof typeof LootKind]; -export enum LootAttributeClassId { - OTHER = 0, - RARITY = 1, - NUTRI_SCORE = 2, -} +export const LootAttributeClass = Object.freeze({ + OTHER: 0, + RARITY: 1, + NUTRI_SCORE: 2, +} as const); +export type LootAttributeClassId = (typeof LootAttributeClass)[keyof typeof LootAttributeClass]; -export enum LootAttributeKindId { - RARITY_NORMAL = 0, - RARITY_RARE = 1, - RARITY_VERY_RARE = 2, - RADIOACTIVE = 3, - SWEET = 4, - NUTRI_SCORE_A = 5, - NUTRI_SCORE_B = 6, - NUTRI_SCORE_C = 7, - NUTRI_SCORE_D = 8, - NUTRI_SCORE_E = 9, -} +export const LootAttributeKind = Object.freeze({ + RARITY_NORMAL: 0, + RARITY_RARE: 1, + RARITY_VERY_RARE: 2, + RADIOACTIVE: 3, + SWEET: 4, + NUTRI_SCORE_A: 5, + NUTRI_SCORE_B: 6, + NUTRI_SCORE_C: 7, + NUTRI_SCORE_D: 8, + NUTRI_SCORE_E: 9, +} as const); +export type LootAttributeKindId = (typeof LootAttributeKind)[keyof typeof LootAttributeKind]; export const lootTemplateMap: Record = { - [LootKindId.NICHTS]: { - id: LootKindId.NICHTS, + [LootKind.NICHTS]: { + id: LootKind.NICHTS, weight: 24, displayName: "Nichts", titleText: "✨Nichts✨", @@ -95,21 +98,21 @@ export const lootTemplateMap: Record = { excludeFromInventory: true, excludeFromDoubleDrops: true, }, - [LootKindId.KADSE]: { - id: LootKindId.KADSE, + [LootKind.KADSE]: { + id: LootKind.KADSE, weight: 4, displayName: "Niedliche Kadse", titleText: "Eine niedliche Kadse", dropDescription: "Awww", emote: "🐈", asset: "assets/loot/01-kadse.jpg", - initialAttributes: [LootAttributeKindId.SWEET], + initialAttributes: [LootAttributeKind.SWEET], attributeAsset: { - [LootAttributeKindId.RADIOACTIVE]: "assets/loot/attributes/01-kadse-verstrahlt.jpg", + [LootAttributeKind.RADIOACTIVE]: "assets/loot/attributes/01-kadse-verstrahlt.jpg", }, }, - [LootKindId.MESSERBLOCK]: { - id: LootKindId.MESSERBLOCK, + [LootKind.MESSERBLOCK]: { + id: LootKind.MESSERBLOCK, weight: 1, displayName: "Messerblock", titleText: "Einen Messerblock", @@ -117,8 +120,8 @@ export const lootTemplateMap: Record = { emote: "🔪", asset: "assets/loot/02-messerblock.jpg", }, - [LootKindId.KUEHLSCHRANK]: { - id: LootKindId.KUEHLSCHRANK, + [LootKind.KUEHLSCHRANK]: { + id: LootKind.KUEHLSCHRANK, weight: 1, displayName: "Sehr teurer Kühlschrank", titleText: "Ein sehr teurer Kühlschrank", @@ -128,18 +131,18 @@ export const lootTemplateMap: Record = { asset: "assets/loot/03-kuehlschrank.jpg", effects: ["Lässt Essen nicht schimmeln"], }, - [LootKindId.DOENER]: { - id: LootKindId.DOENER, + [LootKind.DOENER]: { + id: LootKind.DOENER, weight: 5, displayName: "Döner", titleText: "Einen Döner", dropDescription: "Bewahre ihn gut als Geldanlage auf!", emote: "🥙", asset: "assets/loot/04-doener.jpg", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_C], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_C], }, - [LootKindId.KINN]: { - id: LootKindId.KINN, + [LootKind.KINN]: { + id: LootKind.KINN, weight: 0.5, displayName: "Kinn", titleText: "Ein Kinn", @@ -147,8 +150,8 @@ export const lootTemplateMap: Record = { emote: "👶", asset: "assets/loot/05-kinn.jpg", }, - [LootKindId.KRANKSCHREIBUNG]: { - id: LootKindId.KRANKSCHREIBUNG, + [LootKind.KRANKSCHREIBUNG]: { + id: LootKind.KRANKSCHREIBUNG, weight: 0.5, displayName: "Arbeitsunfähigkeitsbescheinigung", titleText: "Einen gelben Urlaubsschein", @@ -180,8 +183,8 @@ export const lootTemplateMap: Record = { return false; }, }, - [LootKindId.WUERFELWURF]: { - id: LootKindId.WUERFELWURF, + [LootKind.WUERFELWURF]: { + id: LootKind.WUERFELWURF, weight: 4, displayName: "Würfelwurf", titleText: "Einen Wurf mit einem Würfel", @@ -195,8 +198,8 @@ export const lootTemplateMap: Record = { await rollService.rollInChannel(winner.user, channel, 1, 6); }, }, - [LootKindId.GESCHENK]: { - id: LootKindId.GESCHENK, + [LootKind.GESCHENK]: { + id: LootKind.GESCHENK, weight: 2, displayName: "Geschenk", titleText: "Ein Geschenk", @@ -213,18 +216,18 @@ export const lootTemplateMap: Record = { return false; }, }, - [LootKindId.AYRAN]: { - id: LootKindId.AYRAN, + [LootKind.AYRAN]: { + id: LootKind.AYRAN, weight: 1, displayName: "Ayran", titleText: "Einen Ayran", dropDescription: "Der gute von Müller", emote: "🥛", asset: "assets/loot/09-ayran.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_D], // Ref: https://de.openfoodfacts.org/produkt/4388860730685/ayran-ja + initialAttributes: [LootAttributeKind.NUTRI_SCORE_D], // Ref: https://de.openfoodfacts.org/produkt/4388860730685/ayran-ja }, - [LootKindId.PKV]: { - id: LootKindId.PKV, + [LootKind.PKV]: { + id: LootKind.PKV, weight: 1, displayName: "Private Krankenversicherung", titleText: "Eine private Krankenversicherung", @@ -233,8 +236,8 @@ export const lootTemplateMap: Record = { asset: "assets/loot/10-pkv.jpg", effects: ["` +100% ` Chance auf AU 🟢"], }, - [LootKindId.TRICHTER]: { - id: LootKindId.TRICHTER, + [LootKind.TRICHTER]: { + id: LootKind.TRICHTER, weight: 1, displayName: "Trichter", titleText: "Einen Trichter", @@ -242,8 +245,8 @@ export const lootTemplateMap: Record = { emote: ":trichter:", asset: "assets/loot/11-trichter.png", }, - [LootKindId.GRAFIKKARTE]: { - id: LootKindId.GRAFIKKARTE, + [LootKind.GRAFIKKARTE]: { + id: LootKind.GRAFIKKARTE, weight: 1, displayName: "Grafikkarte aus der Zukunft", titleText: "Eine Grafikkarte aus der Zukunft", @@ -251,8 +254,8 @@ export const lootTemplateMap: Record = { emote: "🖥️", asset: "assets/loot/12-grafikkarte.png", }, - [LootKindId.HAENDEDRUCK]: { - id: LootKindId.HAENDEDRUCK, + [LootKind.HAENDEDRUCK]: { + id: LootKind.HAENDEDRUCK, weight: 1, displayName: "Feuchter Händedruck", titleText: "Einen feuchten Händedruck", @@ -261,8 +264,8 @@ export const lootTemplateMap: Record = { asset: "assets/loot/13-haendedruck.jpg", excludeFromInventory: true, }, - [LootKindId.ERLEUCHTUNG]: { - id: LootKindId.ERLEUCHTUNG, + [LootKind.ERLEUCHTUNG]: { + id: LootKind.ERLEUCHTUNG, weight: 1, displayName: "Erleuchtung", titleText: "Eine Erleuchtung", @@ -282,8 +285,8 @@ export const lootTemplateMap: Record = { }); }, }, - [LootKindId.BAN]: { - id: LootKindId.BAN, + [LootKind.BAN]: { + id: LootKind.BAN, weight: 1, displayName: "Willkürban", titleText: "Einen Ban aus reiner Willkür", @@ -304,18 +307,18 @@ export const lootTemplateMap: Record = { ); }, }, - [LootKindId.OETTINGER]: { - id: LootKindId.OETTINGER, + [LootKind.OETTINGER]: { + id: LootKind.OETTINGER, weight: 1, displayName: "Oettinger", titleText: "Ein warmes Oettinger", dropDescription: "Ja dann Prost ne!", emote: "🍺", asset: "assets/loot/16-oettinger.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_B], // Ref: https://archive.is/aonnZ + initialAttributes: [LootAttributeKind.NUTRI_SCORE_B], // Ref: https://archive.is/aonnZ }, - [LootKindId.ACHIEVEMENT]: { - id: LootKindId.ACHIEVEMENT, + [LootKind.ACHIEVEMENT]: { + id: LootKind.ACHIEVEMENT, weight: 1, displayName: "Achievement", titleText: "Ein Achievement", @@ -323,8 +326,8 @@ export const lootTemplateMap: Record = { emote: "🏆", asset: "assets/loot/17-achievement.png", }, - [LootKindId.GME_AKTIE]: { - id: LootKindId.GME_AKTIE, + [LootKind.GME_AKTIE]: { + id: LootKind.GME_AKTIE, weight: 5, displayName: "Wertlose GME-Aktie", titleText: "Eine wertlose GME-Aktie", @@ -332,8 +335,8 @@ export const lootTemplateMap: Record = { emote: "📉", asset: "assets/loot/18-gme.jpg", }, - [LootKindId.FERRIS]: { - id: LootKindId.FERRIS, + [LootKind.FERRIS]: { + id: LootKind.FERRIS, weight: 3, displayName: "Ferris", titleText: "Einen Ferris - Die Krabbe", @@ -341,8 +344,8 @@ export const lootTemplateMap: Record = { emote: "🦀", asset: "assets/loot/19-ferris.png", }, - [LootKindId.HOMEPOD]: { - id: LootKindId.HOMEPOD, + [LootKind.HOMEPOD]: { + id: LootKind.HOMEPOD, weight: 3, displayName: "HomePod", titleText: "Einen Apple:registered: HomePod:copyright:", @@ -350,8 +353,8 @@ export const lootTemplateMap: Record = { emote: "🍎", asset: "assets/loot/20-homepod.jpg", }, - [LootKindId.RADIOACTIVE_WASTE]: { - id: LootKindId.RADIOACTIVE_WASTE, + [LootKind.RADIOACTIVE_WASTE]: { + id: LootKind.RADIOACTIVE_WASTE, weight: 1, displayName: "Radioaktiver Müll", titleText: "Radioaktiver Müll", @@ -361,18 +364,18 @@ export const lootTemplateMap: Record = { asset: "assets/loot/21-radioaktiver-muell.jpg", effects: ["` +5% ` Chance auf leeres Geschenk 🔴"], }, - [LootKindId.SAHNE]: { - id: LootKindId.SAHNE, + [LootKind.SAHNE]: { + id: LootKind.SAHNE, weight: 1, displayName: "Sprühsahne", titleText: "Sprühsahne", dropDescription: "Fürs Frühstück oder so", emote: ":sahne:", asset: "assets/loot/22-sahne.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_D], // Ref: https://de.openfoodfacts.org/produkt/4311501745663/spr%C3%BChsahne-gut-g%C3%BCnstig + initialAttributes: [LootAttributeKind.NUTRI_SCORE_D], // Ref: https://de.openfoodfacts.org/produkt/4311501745663/spr%C3%BChsahne-gut-g%C3%BCnstig }, - [LootKindId.AEHRE]: { - id: LootKindId.AEHRE, + [LootKind.AEHRE]: { + id: LootKind.AEHRE, weight: 1, displayName: "Ehre", titleText: "Ehre aus Mitleid", @@ -386,8 +389,8 @@ export const lootTemplateMap: Record = { await ehre.addPoints(winner.id, 1); }, }, - [LootKindId.CROWDSTRIKE]: { - id: LootKindId.CROWDSTRIKE, + [LootKind.CROWDSTRIKE]: { + id: LootKind.CROWDSTRIKE, weight: 1, displayName: "Crowdstrike Falcon", titleText: "Crowdstrike Falcon Installation", @@ -395,18 +398,18 @@ export const lootTemplateMap: Record = { emote: "🦅", asset: "assets/loot/24-crowdstrike.jpg", }, - [LootKindId.POWERADE_BLAU]: { - id: LootKindId.POWERADE_BLAU, + [LootKind.POWERADE_BLAU]: { + id: LootKind.POWERADE_BLAU, weight: 1, displayName: "Blaue Powerade", titleText: "Blaue Powerade", dropDescription: "Erfrischend erquickend. Besonders mit Vodka. Oder Korn.", asset: "assets/loot/25-powerade-blau.jpg", emote: ":powerade:", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_D], // Ref: https://de.openfoodfacts.org/produkt/90357350/powerrade-mountain-blast-blue-coca-cola + initialAttributes: [LootAttributeKind.NUTRI_SCORE_D], // Ref: https://de.openfoodfacts.org/produkt/90357350/powerrade-mountain-blast-blue-coca-cola }, - [LootKindId.GAULOISES_BLAU]: { - id: LootKindId.GAULOISES_BLAU, + [LootKind.GAULOISES_BLAU]: { + id: LootKind.GAULOISES_BLAU, weight: 1, displayName: "Gauloises Blau", titleText: "Eine Schachtel Gauloises Blau", @@ -415,8 +418,8 @@ export const lootTemplateMap: Record = { emote: "🚬", asset: "assets/loot/26-gauloises-blau.png", }, - [LootKindId.MAXWELL]: { - id: LootKindId.MAXWELL, + [LootKind.MAXWELL]: { + id: LootKind.MAXWELL, weight: 1, displayName: "Maxwell", titleText: "Einen Maxwell", @@ -424,8 +427,8 @@ export const lootTemplateMap: Record = { emote: "😸", asset: "assets/loot/27-maxwell.gif", }, - [LootKindId.SCHICHTBEGINN_ASSE_2]: { - id: LootKindId.SCHICHTBEGINN_ASSE_2, + [LootKind.SCHICHTBEGINN_ASSE_2]: { + id: LootKind.SCHICHTBEGINN_ASSE_2, weight: 4, displayName: "Wärter Asse II", titleText: "Den Schichtbeginn in der Asse II", @@ -439,8 +442,8 @@ export const lootTemplateMap: Record = { await lootRoles.startAsseGuardShift(context, winner, channel); }, }, - [LootKindId.DRECK]: { - id: LootKindId.DRECK, + [LootKind.DRECK]: { + id: LootKind.DRECK, weight: 2, displayName: "Ein Glas Dreck", titleText: "Ein Glas Dreck", @@ -448,8 +451,8 @@ export const lootTemplateMap: Record = { emote: "🫙", asset: "assets/loot/29-dreck.jpg", }, - [LootKindId.EI]: { - id: LootKindId.EI, + [LootKind.EI]: { + id: LootKind.EI, weight: 3, displayName: "Ei", titleText: "Ein Ei", @@ -458,8 +461,8 @@ export const lootTemplateMap: Record = { emote: "🥚", asset: "assets/loot/30-ei.png", }, - [LootKindId.BRAVO]: { - id: LootKindId.BRAVO, + [LootKind.BRAVO]: { + id: LootKind.BRAVO, weight: 2, displayName: "Bravo", titleText: "Eine Bravo vom Dachboden", @@ -467,28 +470,28 @@ export const lootTemplateMap: Record = { emote: "🗞️", asset: "assets/loot/31-bravo.jpg", }, - [LootKindId.VERSCHIMMELTER_DOENER]: { - id: LootKindId.VERSCHIMMELTER_DOENER, + [LootKind.VERSCHIMMELTER_DOENER]: { + id: LootKind.VERSCHIMMELTER_DOENER, weight: ACHTUNG_NICHT_DROPBAR_WEIGHT_KG, displayName: "Verschimmelter Döner", titleText: "Einen verschimmelten Döner", dropDescription: "Du hättest ihn früher essen sollen", emote: "🥙", asset: null, - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_E], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_E], }, - [LootKindId.THUNFISCHSHAKE]: { - id: LootKindId.THUNFISCHSHAKE, + [LootKind.THUNFISCHSHAKE]: { + id: LootKind.THUNFISCHSHAKE, weight: 2, displayName: "Thunfischshake", titleText: "Ein Thunfischshake, serviert von Markus Rühl persönlich", dropDescription: "Nach Rezept zubereitet, bestehend aus Thunfisch und Reiswaffeln", emote: "🍼", asset: "assets/loot/33-thunfischshake.jpg", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_A], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_A], }, - [LootKindId.KAFFEEMUEHLE]: { - id: LootKindId.KAFFEEMUEHLE, + [LootKind.KAFFEEMUEHLE]: { + id: LootKind.KAFFEEMUEHLE, weight: 1, displayName: "Kaffeemühle", titleText: "Eine Kaffeemühle für 400€", @@ -496,8 +499,8 @@ export const lootTemplateMap: Record = { emote: "☕", asset: "assets/loot/34-kaffeemuehle.png", }, - [LootKindId.AWS_RECHNUNG]: { - id: LootKindId.AWS_RECHNUNG, + [LootKind.AWS_RECHNUNG]: { + id: LootKind.AWS_RECHNUNG, weight: 1, displayName: "AWS-Rechnung", titleText: "Ne dicke AWS-Rechnung", @@ -505,18 +508,18 @@ export const lootTemplateMap: Record = { emote: "📦", asset: "assets/loot/35-aws-rechnung.png", }, - [LootKindId.BIBER]: { - id: LootKindId.BIBER, + [LootKind.BIBER]: { + id: LootKind.BIBER, weight: 2, displayName: "Süßer Biber", titleText: "Bóbr", dropDescription: "Bóbr kurwa! Ja pierdolę! Jakie bydlę!", emote: "🦫", asset: "assets/loot/36-biber.jpg", - initialAttributes: [LootAttributeKindId.SWEET], + initialAttributes: [LootAttributeKind.SWEET], }, - [LootKindId.BLEI]: { - id: LootKindId.BLEI, + [LootKind.BLEI]: { + id: LootKind.BLEI, weight: ACHTUNG_NICHT_DROPBAR_WEIGHT_KG, displayName: "Blei", titleText: "Einen Block Blei", @@ -525,8 +528,8 @@ export const lootTemplateMap: Record = { asset: "assets/loot/37-blei.png", initialAttributes: [], }, - [LootKindId.USV]: { - id: LootKindId.USV, + [LootKind.USV]: { + id: LootKind.USV, weight: 2, displayName: "USV", titleText: "Eine kaputte USV", @@ -535,8 +538,8 @@ export const lootTemplateMap: Record = { asset: "assets/loot/38-usv.png", initialAttributes: [], }, - [LootKindId.BAHNCARD_25]: { - id: LootKindId.BAHNCARD_25, + [LootKind.BAHNCARD_25]: { + id: LootKind.BAHNCARD_25, weight: 6, displayName: "BahnCard 25", titleText: "Eine BahnCard 25", @@ -555,7 +558,7 @@ export const lootTemplateMap: Record = { ), onDuplicateDrop: async (context, winner, loot, dropMessage) => { // biome-ignore lint/style/noNonNullAssertion: :shrug: - const newBc = resolveLootTemplate(LootKindId.BAHNCARD_50)!; + const newBc = resolveLootTemplate(LootKind.BAHNCARD_50)!; const newLoot = await lootService.replaceLoot( loot.id, @@ -574,7 +577,7 @@ export const lootTemplateMap: Record = { const newContent = await lootDropService.createDropTakenContent( context, - lootTemplateMap[LootKindId.BAHNCARD_50], + lootTemplateMap[LootKind.BAHNCARD_50], newLoot, winner.user, [ @@ -586,8 +589,8 @@ export const lootTemplateMap: Record = { return false; }, }, - [LootKindId.BAHNCARD_50]: { - id: LootKindId.BAHNCARD_50, + [LootKind.BAHNCARD_50]: { + id: LootKind.BAHNCARD_50, weight: 3, displayName: "BahnCard 50", titleText: "Eine BahnCard 50", @@ -606,7 +609,7 @@ export const lootTemplateMap: Record = { ), onDuplicateDrop: async (context, winner, loot, dropMessage) => { // biome-ignore lint/style/noNonNullAssertion: :shrug: - const newBc = resolveLootTemplate(LootKindId.BAHNCARD_100)!; + const newBc = resolveLootTemplate(LootKind.BAHNCARD_100)!; const newLoot = await lootService.replaceLoot( loot.id, @@ -625,7 +628,7 @@ export const lootTemplateMap: Record = { const newContent = await lootDropService.createDropTakenContent( context, - lootTemplateMap[LootKindId.BAHNCARD_100], + lootTemplateMap[LootKind.BAHNCARD_100], newLoot, winner.user, [ @@ -637,9 +640,9 @@ export const lootTemplateMap: Record = { return false; }, }, - [LootKindId.BAHNCARD_100]: { + [LootKind.BAHNCARD_100]: { // Not droppable, only via duplicate BahnCard 50 - id: LootKindId.BAHNCARD_100, + id: LootKind.BAHNCARD_100, weight: ACHTUNG_NICHT_DROPBAR_WEIGHT_KG, displayName: "BahnCard 100", titleText: "Eine BahnCard 100", @@ -650,8 +653,8 @@ export const lootTemplateMap: Record = { drawCustomAsset: (context, owner, template, loot) => bahnCardService.drawBahncardImage(context, owner, template, loot, true, owner.id), }, - [LootKindId.LABUBU]: { - id: LootKindId.LABUBU, + [LootKind.LABUBU]: { + id: LootKind.LABUBU, weight: 1, displayName: "Labubu", titleText: "Einen Labubu", @@ -659,8 +662,8 @@ export const lootTemplateMap: Record = { emote: "🦦", asset: "assets/loot/42-labubu.jpg", }, - [LootKindId.BABYBEL_ORIGINAL]: { - id: LootKindId.BABYBEL_ORIGINAL, + [LootKind.BABYBEL_ORIGINAL]: { + id: LootKind.BABYBEL_ORIGINAL, weight: 3, displayName: "Mini Babybel® Original", titleText: "Ein Babybel® Original", @@ -668,20 +671,20 @@ export const lootTemplateMap: Record = { "Schon seit 1977 erobert unser roter Superstar die Herzen aller Snack-Liebhaber. Er ist nicht nur praktisch, lecker und immer für eine gute Portion Spaß zu haben, sondern auch ohne Gentechnik und ohne Zusatz von Konservierungsstoffen. Dank der natürlichen Reifung in seiner Wachshülle ist er außerdem laktosefrei sowie reich an Protein und Kalzium.", emote: "🧀", asset: "assets/loot/43-bb-original.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_C], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_C], }, - [LootKindId.BABYBEL_LIGHT]: { - id: LootKindId.BABYBEL_LIGHT, + [LootKind.BABYBEL_LIGHT]: { + id: LootKind.BABYBEL_LIGHT, weight: 2, displayName: "Mini Babybel® Light", titleText: "Ein Babybel® Light", dropDescription: "Der kleine Käse mit der roten Wachsverpackung, mit weniger Fett!", emote: "🧀", asset: "assets/loot/44-bb-light.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_C], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_C], }, - [LootKindId.BABYBEL_CHEDDAR]: { - id: LootKindId.BABYBEL_CHEDDAR, + [LootKind.BABYBEL_CHEDDAR]: { + id: LootKind.BABYBEL_CHEDDAR, weight: 1, displayName: "Mini Babybel® Cheddar-Geschmack", titleText: "Ein Babybel® Cheddar-Geschmack", @@ -689,10 +692,10 @@ export const lootTemplateMap: Record = { "Mini Babybel® mit Cheddar-Geschmack erfreut Groß und Klein und bringt Abwechslung in die Lunch-Box.\n\nFür Vegetarier geeignet.", emote: "🧀", asset: "assets/loot/45-bb-cheddar.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_D], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_D], }, - [LootKindId.BABYBEL_EMMENTALER]: { - id: LootKindId.BABYBEL_EMMENTALER, + [LootKind.BABYBEL_EMMENTALER]: { + id: LootKind.BABYBEL_EMMENTALER, weight: 1, displayName: "Mini Babybel® Emmentaler-Geschmack", titleText: "Ein Babybel® Emmentaler-Geschmack", @@ -700,10 +703,10 @@ export const lootTemplateMap: Record = { "Mini Babybel® mit feinem Emmentaler-Geschmack sorgt für herzhafte Snack-Momente und bereitet viel Vergnügen bei Groß und Klein.", emote: "🧀", asset: "assets/loot/46-bb-emmentaler.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_D], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_D], }, - [LootKindId.BABYBEL_PROTEIN]: { - id: LootKindId.BABYBEL_PROTEIN, + [LootKind.BABYBEL_PROTEIN]: { + id: LootKind.BABYBEL_PROTEIN, weight: 1, displayName: "Mini Babybel® High Protein", titleText: "Ein Babybel® High Protein", @@ -711,10 +714,10 @@ export const lootTemplateMap: Record = { "Lecker Käse in rotem Wachs. Genau der gleiche wie der blaue, aber für echte Männer.", emote: "🧀", asset: "assets/loot/47-bb-protein.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_C], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_C], }, - [LootKindId.BABYBEL_GOUDA]: { - id: LootKindId.BABYBEL_GOUDA, + [LootKind.BABYBEL_GOUDA]: { + id: LootKind.BABYBEL_GOUDA, weight: 1, displayName: "Mini Babybel® Unser Würziger", titleText: "Ein Babybel® Unser Würziger", @@ -722,10 +725,10 @@ export const lootTemplateMap: Record = { "Babybel® Unser Würziger ist eine Varietät des klassischen Babybel® Original. Er vereint alle Vorteile eines leckeren Käse-Snacks mit einem würzig-nussigen Geschmack (wir wollten es nicht einfach nur Gouda nennen) und sorgt auf diese Weise für ein etwas intensiveres Babybel®-Erlebnis.\n\nDurch seinen intensiv-herzhaften Geschmack eignet sich der würzig-leckere Snack sehr gut für den kleinen Hunger zwischendurch und bietet damit auch Käseliebhabern mit einem intensiveren Käsegeschmack eine optimale Ergänzung zur klassischen Variante.", emote: "🧀", asset: "assets/loot/48-bb-gouda.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_D], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_D], }, - [LootKindId.BABYBEL_VEGAN]: { - id: LootKindId.BABYBEL_VEGAN, + [LootKind.BABYBEL_VEGAN]: { + id: LootKind.BABYBEL_VEGAN, weight: 1, displayName: "Mini Babybel® Vegan", titleText: "Ein Babybel® Vegan", @@ -733,17 +736,17 @@ export const lootTemplateMap: Record = { "Den beliebten Babybel® gibt es jetzt auch als vegane Käsealternative, ganz ohne Milch und schnell erkennbar dank seiner grünen Wachshülle. Mit seinem milden Geschmack und der cremigen Textur ist der vegane Babybel® eine leckere und praktische Alternative als Snack für zuhause oder unterwegs.\n\nDer vegane Babybel® ist erhältlich im praktischen, recyclebaren Papierbeutel und ist eigentlich nur ein Block Kokosfett mit Salz.", emote: "🧀", asset: "assets/loot/49-bb-vegan.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_E], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_E], }, - [LootKindId.BABYBEL_EXODIA]: { - id: LootKindId.BABYBEL_EXODIA, + [LootKind.BABYBEL_EXODIA]: { + id: LootKind.BABYBEL_EXODIA, weight: ACHTUNG_NICHT_DROPBAR_WEIGHT_KG, displayName: "Mini Babybel® Exodia", titleText: "Mini Babybel® Exodia", dropDescription: "Du hast das Spiel gewonnen.", emote: "🧀", asset: "assets/loot/50-bb-exodia.png", - initialAttributes: [LootAttributeKindId.NUTRI_SCORE_E], + initialAttributes: [LootAttributeKind.NUTRI_SCORE_E], }, } as const; @@ -766,70 +769,70 @@ export const lootTemplates: LootTemplate[] = Object.values(lootTemplateMap); */ export const lootAttributeTemplates: LootAttributeTemplate[] = [ { - id: LootAttributeKindId.RARITY_NORMAL, - classId: LootAttributeClassId.RARITY, + id: LootAttributeKind.RARITY_NORMAL, + classId: LootAttributeClass.RARITY, displayName: "Normal", shortDisplay: "", initialDropWeight: 90, }, { - id: LootAttributeKindId.RARITY_RARE, - classId: LootAttributeClassId.RARITY, + id: LootAttributeKind.RARITY_RARE, + classId: LootAttributeClass.RARITY, displayName: "Selten", shortDisplay: "⭐", initialDropWeight: 10, }, { - id: LootAttributeKindId.RARITY_VERY_RARE, - classId: LootAttributeClassId.RARITY, + id: LootAttributeKind.RARITY_VERY_RARE, + classId: LootAttributeClass.RARITY, displayName: "Sehr Selten", shortDisplay: "🌟", initialDropWeight: 1, }, { - id: LootAttributeKindId.RADIOACTIVE, - classId: LootAttributeClassId.OTHER, + id: LootAttributeKind.RADIOACTIVE, + classId: LootAttributeClass.OTHER, displayName: "Verstrahlt", shortDisplay: "☢️", color: 0xff_ff_ff, }, { - id: LootAttributeKindId.SWEET, - classId: LootAttributeClassId.OTHER, + id: LootAttributeKind.SWEET, + classId: LootAttributeClass.OTHER, displayName: "Süß", shortDisplay: "🍬", }, { - id: LootAttributeKindId.NUTRI_SCORE_A, - classId: LootAttributeClassId.NUTRI_SCORE, + id: LootAttributeKind.NUTRI_SCORE_A, + classId: LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score A", shortDisplay: "🟩", color: 0x00_ff_00, }, { - id: LootAttributeKindId.NUTRI_SCORE_B, - classId: LootAttributeClassId.NUTRI_SCORE, + id: LootAttributeKind.NUTRI_SCORE_B, + classId: LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score B", shortDisplay: "🟨", color: 0x99_ff_00, }, { - id: LootAttributeKindId.NUTRI_SCORE_C, - classId: LootAttributeClassId.NUTRI_SCORE, + id: LootAttributeKind.NUTRI_SCORE_C, + classId: LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score C", shortDisplay: "🟧", color: 0xff_ff_00, }, { - id: LootAttributeKindId.NUTRI_SCORE_D, - classId: LootAttributeClassId.NUTRI_SCORE, + id: LootAttributeKind.NUTRI_SCORE_D, + classId: LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score D", shortDisplay: "🟥", color: 0xff_99_00, }, { - id: LootAttributeKindId.NUTRI_SCORE_E, - classId: LootAttributeClassId.NUTRI_SCORE, + id: LootAttributeKind.NUTRI_SCORE_E, + classId: LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score E", shortDisplay: "🟥", color: 0xff_00_00, @@ -859,14 +862,14 @@ export function getAttributesByClass( export function extractRarityAttribute( attributes: readonly Readonly[], ): Readonly | undefined { - const rarities = getAttributesByClass(attributes, LootAttributeClassId.RARITY); + const rarities = getAttributesByClass(attributes, LootAttributeClass.RARITY); return rarities[0] ?? undefined; } export function extractNonRarityAttributes( attributes: readonly Readonly[], ): Readonly[] { - return attributes.filter(a => a.attributeClassId !== LootAttributeClassId.RARITY); + return attributes.filter(a => a.attributeClassId !== LootAttributeClass.RARITY); } export function itemHasAttribute( diff --git a/src/service/lootDegradation.ts b/src/service/lootDegradation.ts index 97a4a97b..b10e0c57 100644 --- a/src/service/lootDegradation.ts +++ b/src/service/lootDegradation.ts @@ -3,7 +3,7 @@ import type { BotContext } from "#context.ts"; import * as time from "#utils/time.ts"; import * as lootService from "#service/loot.ts"; -import { LootAttributeKindId, LootKindId, resolveLootTemplate } from "#service/lootData.ts"; +import { LootAttributeKind, LootKind, resolveLootTemplate } from "#service/lootData.ts"; import log from "#log"; import { randomEntry } from "#service/random.ts"; @@ -12,7 +12,7 @@ export async function degradeItems(_context: BotContext) { const now = Date.now(); const maxKebabAge = time.days(3); - const kebabs = await lootService.getLootsByKindId(LootKindId.DOENER); + const kebabs = await lootService.getLootsByKindId(LootKind.DOENER); for (const k of kebabs) { const itemAge = now - new Date(k.claimedAt).getTime(); @@ -20,7 +20,7 @@ export async function degradeItems(_context: BotContext) { continue; } - const fridges = await lootService.getUserLootsByTypeId(k.winnerId, LootKindId.KUEHLSCHRANK); + const fridges = await lootService.getUserLootsByTypeId(k.winnerId, LootKind.KUEHLSCHRANK); if (fridges.length > 0) { // user has a fridge, don't verschimmel döner @@ -31,7 +31,7 @@ export async function degradeItems(_context: BotContext) { k.id, { displayName: "Verschimmelter Döner", - lootKindId: LootKindId.VERSCHIMMELTER_DOENER, + lootKindId: LootKind.VERSCHIMMELTER_DOENER, winnerId: k.winnerId, claimedAt: k.claimedAt, guildId: k.guildId, @@ -46,7 +46,7 @@ export async function degradeItems(_context: BotContext) { export async function exposeWithRadiation(context: BotContext) { // currently also includes sweets that are already radioactive - const sweets = await lootService.getLootsWithAttribute(LootAttributeKindId.SWEET); + const sweets = await lootService.getLootsWithAttribute(LootAttributeKind.SWEET); const targetLoot = randomEntry(sweets); if (!targetLoot) { @@ -55,7 +55,7 @@ export async function exposeWithRadiation(context: BotContext) { const wasteItems = await lootService.getUserLootsByTypeId( targetLoot.winnerId, - LootKindId.RADIOACTIVE_WASTE, + LootKind.RADIOACTIVE_WASTE, ); if (wasteItems.length === 0) { return; @@ -63,7 +63,7 @@ export async function exposeWithRadiation(context: BotContext) { const attributeAdded = await lootService.addLootAttributeIfNotPresent( targetLoot.id, - LootAttributeKindId.RADIOACTIVE, + LootAttributeKind.RADIOACTIVE, ); if (!attributeAdded) { return; @@ -86,7 +86,7 @@ export async function runHalfLife(context: BotContext) { logger.info("Running half life"); - const allWaste = await lootService.getLootsByKindId(LootKindId.RADIOACTIVE_WASTE); + const allWaste = await lootService.getLootsByKindId(LootKind.RADIOACTIVE_WASTE); // See: https://github.com/NullDev/CSZ-Bot/issues/470 const targetWasteCount = Math.ceil(allWaste.length / 2); @@ -103,7 +103,7 @@ export async function runHalfLife(context: BotContext) { return; } - const leadTemplate = resolveLootTemplate(LootKindId.BLEI); + const leadTemplate = resolveLootTemplate(LootKind.BLEI); if (!leadTemplate) { logger.error("Could not resolve loot template for lead."); return; diff --git a/src/service/lootDrop.ts b/src/service/lootDrop.ts index 09e8a7eb..902e5247 100644 --- a/src/service/lootDrop.ts +++ b/src/service/lootDrop.ts @@ -27,9 +27,9 @@ import { randomBoolean, randomEntry, randomEntryWeighted } from "#service/random import * as lootService from "#service/loot.ts"; import { - LootAttributeClassId, + LootAttributeClass, lootAttributeTemplates, - LootKindId, + LootKind, lootTemplates, } from "#service/lootData.ts"; @@ -160,11 +160,11 @@ export async function postLootDrop( const template = randomEntryWeighted(lootTemplates, weights); - const rarities = lootAttributeTemplates.filter(a => a.classId === LootAttributeClassId.RARITY); + const rarities = lootAttributeTemplates.filter(a => a.classId === LootAttributeClass.RARITY); const rarityWeights = rarities.map(a => a.initialDropWeight ?? 0); const rarityAttribute = - template.id === LootKindId.NICHTS ? null : randomEntryWeighted(rarities, rarityWeights); + template.id === LootKind.NICHTS ? null : randomEntryWeighted(rarities, rarityWeights); const claimedLoot = await lootService.createLoot( template, @@ -322,7 +322,7 @@ export async function createDropTakenContent( const lootAttributes = await lootService.getLootAttributes(claimedLoot.id); const rarityAttribute = lootAttributes.filter( - a => a.attributeClassId === LootAttributeClassId.RARITY, + a => a.attributeClassId === LootAttributeClass.RARITY, )[0]; if (rarityAttribute) { @@ -368,7 +368,7 @@ async function getDropWeightAdjustments( user: User, weights: readonly number[], ): Promise { - const waste = await lootService.getUserLootCountById(user.id, LootKindId.RADIOACTIVE_WASTE); + const waste = await lootService.getUserLootCountById(user.id, LootKind.RADIOACTIVE_WASTE); const messages = []; let wasteFactor = 1; @@ -380,7 +380,7 @@ async function getDropWeightAdjustments( ); } - const pkv = await lootService.getUserLootCountById(user.id, LootKindId.PKV); + const pkv = await lootService.getUserLootCountById(user.id, LootKind.PKV); let pkvFactor = 1; if (pkv > 0) { pkvFactor = 2; @@ -388,8 +388,8 @@ async function getDropWeightAdjustments( } const newWeights = [...weights]; - newWeights[LootKindId.NICHTS] = Math.ceil(weights[LootKindId.NICHTS] * wasteFactor) | 0; - newWeights[LootKindId.KRANKSCHREIBUNG] = (weights[LootKindId.KRANKSCHREIBUNG] * pkvFactor) | 0; + newWeights[LootKind.NICHTS] = Math.ceil(weights[LootKind.NICHTS] * wasteFactor) | 0; + newWeights[LootKind.KRANKSCHREIBUNG] = (weights[LootKind.KRANKSCHREIBUNG] * pkvFactor) | 0; return { messages, diff --git a/src/service/lootRoles.ts b/src/service/lootRoles.ts index b0cdf60f..85ef95ec 100644 --- a/src/service/lootRoles.ts +++ b/src/service/lootRoles.ts @@ -2,7 +2,7 @@ import type { GuildChannel, GuildMember, TextChannel } from "discord.js"; import type { BotContext } from "#context.ts"; -import { LootKindId } from "#service/lootData.ts"; +import { LootKind } from "#service/lootData.ts"; import * as lootService from "#service/loot.ts"; import log from "#log"; @@ -42,7 +42,7 @@ export async function checkExpiredShifts(context: BotContext) { for (const m of currentGuards.values()) { const drops = await lootService.getUserLootsByTypeId( m.user.id, - LootKindId.SCHICHTBEGINN_ASSE_2, + LootKind.SCHICHTBEGINN_ASSE_2, ); log.info({ member: m.id, drops: drops.length }, "Checking AsseGuard shift"); diff --git a/src/service/pet.ts b/src/service/pet.ts index 66b34292..55da2df3 100644 --- a/src/service/pet.ts +++ b/src/service/pet.ts @@ -1,21 +1,23 @@ import type { User } from "discord.js"; import * as lootService from "#service/loot.ts"; -import { LootKindId } from "./lootData.ts"; +import { LootKind } from "./lootData.ts"; import * as pet from "#storage/pet.ts"; import * as lootData from "#service/lootData.ts"; const petCandidates = new Set([ - LootKindId.KADSE, - LootKindId.BIBER, - LootKindId.FERRIS, - LootKindId.OETTINGER, - LootKindId.MAXWELL, + LootKind.KADSE, + LootKind.BIBER, + LootKind.FERRIS, + LootKind.OETTINGER, + LootKind.MAXWELL, ]); export async function getPetCandidates(user: User) { + type ValidPets = typeof petCandidates extends Set ? U : never; + const inventory = await lootService.getInventoryContents(user); - return inventory.filter(i => petCandidates.has(i.lootKindId)); + return inventory.filter(i => petCandidates.has(i.lootKindId as ValidPets)); } export async function setPet(user: User, lootId: number, petName: string) { diff --git a/src/storage/db/model.ts b/src/storage/db/model.ts index ee13af82..75f1a13d 100644 --- a/src/storage/db/model.ts +++ b/src/storage/db/model.ts @@ -1,3 +1,4 @@ +import type { LootAttributeClassId, LootAttributeKindId, LootKindId } from "#service/lootData.ts"; import type { Snowflake } from "discord.js"; import type { ColumnType, Generated, GeneratedAlways, Insertable, Selectable } from "kysely"; @@ -248,7 +249,7 @@ export interface LootTable extends AuditedTable { id: GeneratedAlways; displayName: string; - lootKindId: number; + lootKindId: LootKindId; winnerId: string; /** Different from createdAt. If the item is replaced, this may be copied form the previous loot item */ claimedAt: ColumnType; // TODO: Date is not supported by the DB driver @@ -271,8 +272,8 @@ export interface LootAttributeTable extends AuditedTable { id: GeneratedAlways; lootId: LootId; - attributeKindId: number; - attributeClassId: number; + attributeKindId: LootAttributeKindId; + attributeClassId: LootAttributeClassId; displayName: string; shortDisplay: string; diff --git a/src/storage/loot.ts b/src/storage/loot.ts index 58292bd5..7d45748a 100644 --- a/src/storage/loot.ts +++ b/src/storage/loot.ts @@ -20,14 +20,19 @@ import type { } from "./db/model.ts"; import db from "#db"; -import { resolveLootAttributeTemplate, type LootAttributeKindId } from "#service/lootData.ts"; +import { + type LootKindId, + resolveLootAttributeTemplate, + type LootAttributeKindId, + type LootAttributeClassId, +} from "#service/lootData.ts"; export type LootUseCommandInteraction = ChatInputCommandInteraction & { channel: GuildTextBasedChannel; }; export interface LootTemplate { - id: number; + id: LootKindId; weight: number; displayName: string; titleText: string; @@ -82,8 +87,8 @@ export interface LootTemplate { } export interface LootAttributeTemplate { - id: number; - classId: number; + id: LootAttributeKindId; + classId: LootAttributeClassId; displayName: string; shortDisplay: string; color?: number; @@ -93,15 +98,16 @@ export interface LootAttributeTemplate { const notDeleted = (eb: ExpressionBuilder) => eb.or([eb("deletedAt", "is", null), eb("deletedAt", ">", sql`current_timestamp`)]); -const hasAttribute = (attributeKindId: number) => (eb: ExpressionBuilder) => - eb( - "id", - "in", - eb - .selectFrom("lootAttribute") - .where("attributeKindId", "=", attributeKindId) - .select("lootId"), - ); +const hasAttribute = + (attributeKindId: LootAttributeKindId) => (eb: ExpressionBuilder) => + eb( + "id", + "in", + eb + .selectFrom("lootAttribute") + .where("attributeKindId", "=", attributeKindId) + .select("lootId"), + ); export async function createLoot( template: LootTemplate, @@ -197,7 +203,7 @@ export async function findOfMessage(message: Message, ctx = db()) { .executeTakeFirst(); } -export async function getUserLootsByTypeId(userId: User["id"], lootKindId: number, ctx = db()) { +export async function getUserLootsByTypeId(userId: User["id"], lootKindId: LootKindId, ctx = db()) { return await ctx .selectFrom("loot") .where("winnerId", "=", userId) @@ -209,7 +215,7 @@ export async function getUserLootsByTypeId(userId: User["id"], lootKindId: numbe export async function getUserLootsWithAttribute( userId: User["id"], - attributeKindId: number, + attributeKindId: LootAttributeKindId, ctx = db(), ) { return await ctx @@ -231,7 +237,7 @@ export async function getUserLootById(userId: User["id"], lootId: LootId, ctx = .executeTakeFirst(); } -export async function getLootsByKindId(lootKindId: number, ctx = db()) { +export async function getLootsByKindId(lootKindId: LootKindId, ctx = db()) { return await ctx .selectFrom("loot") .where("lootKindId", "=", lootKindId) @@ -240,7 +246,7 @@ export async function getLootsByKindId(lootKindId: number, ctx = db()) { .execute(); } -export async function getLootsWithAttribute(attributeKindId: number, ctx = db()) { +export async function getLootsWithAttribute(attributeKindId: LootAttributeKindId, ctx = db()) { return await ctx .selectFrom("loot") .where(notDeleted) diff --git a/src/storage/migrations/10-loot-attributes.ts b/src/storage/migrations/10-loot-attributes.ts index a8a872b5..7007919a 100644 --- a/src/storage/migrations/10-loot-attributes.ts +++ b/src/storage/migrations/10-loot-attributes.ts @@ -37,8 +37,8 @@ export async function up(db: Kysely) { .insertInto("lootAttribute") .values({ lootId: id, - attributeClassId: 1, // LootAttributeClassId.RARITY - attributeKindId: 0, // LootAttributeKindId.RARITY_NORMAL + attributeClassId: 1, // LootAttributeClass.RARITY + attributeKindId: 0, // LootAttributeKind.RARITY_NORMAL displayName: "Normal", shortDisplay: "", color: null, @@ -47,13 +47,13 @@ export async function up(db: Kysely) { .returningAll() .executeTakeFirstOrThrow(); - if (lootKindId === 1 /* LootKindId.KADSE */ || lootKindId === 36 /* LootKindId.BIBER */) { + if (lootKindId === 1 /* LootKind.KADSE */ || lootKindId === 36 /* LootKind.BIBER */) { await db .insertInto("lootAttribute") .values({ lootId: id, - attributeClassId: 0, // LootAttributeClassId.OTHER - attributeKindId: 4, // LootAttributeKindId.SWEET + attributeClassId: 0, // LootAttributeClass.OTHER + attributeKindId: 4, // LootAttributeKind.SWEET displayName: "Süß", shortDisplay: "🍬", color: null, diff --git a/src/storage/migrations/16-nutri-score.ts b/src/storage/migrations/16-nutri-score.ts index 72cfe405..91e18886 100644 --- a/src/storage/migrations/16-nutri-score.ts +++ b/src/storage/migrations/16-nutri-score.ts @@ -4,14 +4,14 @@ export async function up(db: Kysely): Promise { const allLoots = await db.selectFrom("loot").selectAll().execute(); for (const loot of allLoots) { switch (loot.lootKindId) { - case 33: // LootKindId.THUNFISCHSHAKE: + case 33: // LootKind.THUNFISCHSHAKE: await db .insertInto("lootAttribute") .orIgnore() .values({ lootId: loot.id, - attributeKindId: 5, // LootAttributeKindId.NUTRI_SCORE_A, - attributeClassId: 2, // LootAttributeClassId.NUTRI_SCORE, + attributeKindId: 5, // LootAttributeKind.NUTRI_SCORE_A, + attributeClassId: 2, // LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score A", shortDisplay: "🟩", color: 0x00_ff_00, @@ -19,14 +19,14 @@ export async function up(db: Kysely): Promise { }) .execute(); break; - case 16: // LootKindId.OETTINGER: + case 16: // LootKind.OETTINGER: await db .insertInto("lootAttribute") .orIgnore() .values({ lootId: loot.id, - attributeKindId: 6, // LootAttributeKindId.NUTRI_SCORE_B, - attributeClassId: 2, // LootAttributeClassId.NUTRI_SCORE, + attributeKindId: 6, // LootAttributeKind.NUTRI_SCORE_B, + attributeClassId: 2, // LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score B", shortDisplay: "🟨", color: 0x99_ff_00, @@ -34,14 +34,14 @@ export async function up(db: Kysely): Promise { }) .execute(); break; - case 4: // LootKindId.DOENER: + case 4: // LootKind.DOENER: await db .insertInto("lootAttribute") .orIgnore() .values({ lootId: loot.id, - attributeKindId: 7, // LootAttributeKindId.NUTRI_SCORE_C, - attributeClassId: 2, // LootAttributeClassId.NUTRI_SCORE, + attributeKindId: 7, // LootAttributeKind.NUTRI_SCORE_C, + attributeClassId: 2, // LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score C", shortDisplay: "🟧", color: 0xff_ff_00, @@ -49,16 +49,16 @@ export async function up(db: Kysely): Promise { }) .execute(); break; - case 25: // LootKindId.POWERADE_BLAU: - case 22: // LootKindId.SAHNE: - case 9: // LootKindId.AYRAN: + case 25: // LootKind.POWERADE_BLAU: + case 22: // LootKind.SAHNE: + case 9: // LootKind.AYRAN: await db .insertInto("lootAttribute") .orIgnore() .values({ lootId: loot.id, - attributeKindId: 8, // LootAttributeKindId.NUTRI_SCORE_D, - attributeClassId: 2, // LootAttributeClassId.NUTRI_SCORE, + attributeKindId: 8, // LootAttributeKind.NUTRI_SCORE_D, + attributeClassId: 2, // LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score D", shortDisplay: "🟥", color: 0xff_99_00, @@ -66,14 +66,14 @@ export async function up(db: Kysely): Promise { }) .execute(); break; - case 32: // LootKindId.VERSCHIMMELTER_DOENER: + case 32: // LootKind.VERSCHIMMELTER_DOENER: await db .insertInto("lootAttribute") .orIgnore() .values({ lootId: loot.id, - attributeKindId: 9, // LootAttributeKindId.NUTRI_SCORE_E, - attributeClassId: 2, // LootAttributeClassId.NUTRI_SCORE, + attributeKindId: 9, // LootAttributeKind.NUTRI_SCORE_E, + attributeClassId: 2, // LootAttributeClass.NUTRI_SCORE, displayName: "Nutri-Score E", shortDisplay: "🟥", diff --git a/tsconfig.json b/tsconfig.json index a8a8639c..ae053eda 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "lib": ["esnext"], "allowImportingTsExtensions": true, + "erasableSyntaxOnly": true, // Additional Checks // "noUnusedLocals": true,