diff --git a/src/services/treasureData.ts b/src/services/treasureData.ts new file mode 100644 index 0000000..489e6ab --- /dev/null +++ b/src/services/treasureData.ts @@ -0,0 +1,325 @@ +import { IndividualTreasureTable, HoardTresureTable } from './treasureService'; + +let individualTreasureData: IndividualTreasureTable[] = [ + { + name: 'Individual Treasure: Challence 0-4', + notes: '', + tags: ['Individual Treasure', 'CR0','CR1','CR2', 'CR3', 'CR4', 'Challenge 0-4', 'treasure'], + dice: [100], + possibleCoinRewards: [ + { + keys: [1,30], + coinCalc: [ + { + type: 'CP', + rollCount: 5, + diceType: 6, + multiplier: 1, + avg: 17 + } + ] + }, + { + keys: [31,60], + coinCalc: [ + { + type: 'SP', + rollCount: 4, + diceType: 6, + multiplier: 1, + avg: 14 + } + ] + }, + { + keys: [61,70], + coinCalc: [ + { + type: 'EP', + rollCount: 3, + diceType: 6, + multiplier: 1, + avg: 10 + } + ] + }, + { + keys: [71,95], + coinCalc: [ + { + type: 'GP', + rollCount: 3, + diceType: 6, + multiplier: 1, + avg: 10 + } + ] + }, + { + keys: [96,100], + coinCalc: [ + { + type: 'PP', + rollCount: 1, + diceType: 6, + multiplier: 1, + avg: 3 + } + ] + } + ] + }, + { + name: 'Individual Treasure: Challence 5-10', + notes: '', + tags: ['Individual Treasure', 'CR5','CR6','CR7', 'CR8', 'CR9', 'CR10', 'Challenge 5-10', 'treasure'], + dice: [100], + possibleCoinRewards: [ + { + keys: [1,30], + coinCalc: [ + { + type: 'CP', + rollCount: 4, + diceType: 6, + multiplier: 100, + avg: 1400 + }, + { + type: 'EP', + rollCount: 1, + diceType: 6, + multiplier: 10, + avg: 35 + } + ] + }, + { + keys: [31,60], + coinCalc: [ + { + type: 'SP', + rollCount: 6, + diceType: 6, + multiplier: 10, + avg: 210 + }, + { + type: 'GP', + rollCount: 2, + diceType: 6, + multiplier: 10, + avg: 70 + } + ] + }, + { + keys: [61,70], + coinCalc: [ + { + type: 'EP', + rollCount: 3, + diceType: 6, + multiplier: 10, + avg: 105 + }, + { + type: 'GP', + rollCount: 2, + diceType: 6, + multiplier: 10, + avg: 70 + } + ] + }, + { + keys: [71,95], + coinCalc: [ + { + type: 'GP', + rollCount: 4, + diceType: 6, + multiplier: 10, + avg: 140 + } + ] + }, + { + keys: [96,100], + coinCalc: [ + { + type: 'GP', + rollCount: 2, + diceType: 6, + multiplier: 10, + avg: 70 + }, + { + type: 'PP', + rollCount: 2, + diceType: 6, + multiplier: 1, + avg: 10 + } + ] + } + ] + }, + { + name: 'Individual Treasure: Challence 11-16', + notes: '', + tags: ['Individual Treasure', 'CR11', 'CR12', 'CR13', 'CR14', 'CR15', 'CR16', 'Challenge 11-16', 'treasure'], + dice: [100], + possibleCoinRewards: [ + { + keys: [1,20], + coinCalc: [ + { + type: 'SP', + rollCount: 4, + diceType: 6, + multiplier: 100, + avg: 1400 + }, + { + type: 'GP', + rollCount: 1, + diceType: 6, + multiplier: 100, + avg: 350 + } + ] + }, + { + keys: [21,35], + coinCalc: [ + { + type: 'EP', + rollCount: 1, + diceType: 6, + multiplier: 100, + avg: 350 + }, + { + type: 'GP', + rollCount: 1, + diceType: 6, + multiplier: 100, + avg: 350 + } + ] + }, + { + keys: [36,75], + coinCalc: [ + { + type: 'GP', + rollCount: 2, + diceType: 6, + multiplier: 100, + avg: 700 + }, + { + type: 'PP', + rollCount: 1, + diceType: 6, + multiplier: 10, + avg: 35 + } + ] + }, + { + keys: [76,100], + coinCalc: [ + { + type: 'GP', + rollCount: 2, + diceType: 6, + multiplier: 100, + avg: 700 + }, + { + type: 'EP', + rollCount: 2, + diceType: 6, + multiplier: 10, + avg: 70 + } + ] + } + ] + }, + { + name: 'Individual Treasure: Challence 17+', + notes: '', + tags: ['Individual Treasure', 'CR17', 'CR18', 'CR19', 'CR20', 'CR21', 'CR22', 'Challenge 17+', 'treasure'], + dice: [100], + possibleCoinRewards: [ + { + keys: [1,15], + coinCalc: [ + { + type: 'EP', + rollCount: 2, + diceType: 6, + multiplier: 1000, + avg: 7000 + }, + { + type: 'GP', + rollCount: 8, + diceType: 6, + multiplier: 100, + avg: 2800 + } + ] + }, + { + keys: [16,55], + coinCalc: [ + { + type: 'GP', + rollCount: 1, + diceType: 6, + multiplier: 1000, + avg: 3500 + }, + { + type: 'PP', + rollCount: 1, + diceType: 6, + multiplier: 100, + avg: 350 + } + ] + }, + { + keys: [56,100], + coinCalc: [ + { + type: 'GP', + rollCount: 1, + diceType: 6, + multiplier: 1000, + avg: 3500 + }, + { + type: 'PP', + rollCount: 2, + diceType: 6, + multiplier: 100, + avg: 700 + } + ] + } + ] + }, +]; + +let hoardTreasureData: HoardTresureTable[] = [ + +]; + +export { + individualTreasureData +} diff --git a/src/services/treasureService.ts b/src/services/treasureService.ts new file mode 100644 index 0000000..0a0aa69 --- /dev/null +++ b/src/services/treasureService.ts @@ -0,0 +1,194 @@ +import { d } from './dice'; +import { individualTreasureData } from './treasureData'; + +class TreasureService { + private individualRewardsTables: RandomIndividualTreasureTable[] = []; + private tableByName: {[tableName: string]: RandomIndividualTreasureTable} = {}; + private tablesByTags: {[tagName: string]: RandomIndividualTreasureTable[]} = {}; + private tags: Set = new Set(); + + constructor() { + console.time('TreasureServiceStartup'); + for (let i in individualTreasureData) { + let table = individualTreasureData[i]; + let randomTable: RandomIndividualTreasureTable = new RandomIndividualTreasureTable(table); + this.individualRewardsTables.push(randomTable); + this.tableByName[table.name] = randomTable; + if (table.tags) { + for (let j in table.tags) { + let tag: string = table.tags[j]; + if (!this.tablesByTags[tag]) { + this.tablesByTags[tag] = []; + } + this.tags.add(tag); + this.tablesByTags[tag].push(randomTable); + } + } + } + console.timeEnd('TreasureServiceStartup'); + } + + public getTablesWithTag(tag: string) { + return this.tablesByTags[tag]; + } + + public getTable(name: string) { + return this.tableByName[name]; + } + + public getTags() { + return this.tags; + } + + public searchForTable(search: string) { + let answer = this.individualRewardsTables.filter((table: RandomIndividualTreasureTable) => { + return table.name.toLowerCase().indexOf(search.toLowerCase()) !== -1 || table.getTags().join(' ').toLowerCase().indexOf(search.toLowerCase()) !== -1; + }).map((table: RandomIndividualTreasureTable) => { + let score = search.length / table.name.length; + return { + table: table, + score: score + }; + }).sort((a: {table: RandomIndividualTreasureTable, score: number}, b: {table: RandomIndividualTreasureTable, score: number}) => { + return a.score - b.score; + }).map((tableScore: {table: RandomIndividualTreasureTable, score: number}) => { + return tableScore.table; + }); + + return answer; + } +} + +class RandomIndividualTreasureTable { + public name: string; + public dice: number[]; + private indexedResults: CoinRewards[] = []; + private config: IndividualTreasureTable; + + constructor(config: IndividualTreasureTable) { + this.name = config.name; + this.dice = config.dice; + this.constructIndex(config.possibleCoinRewards); + this.config = config; + } + + public roll(input?: number) { + let testRoll: number = this.getRoll(); + if (!this.isValidInput(testRoll)) { + console.log(testRoll); + debugger; + } + if (!input || !this.isValidInput(input)) { + input = this.getRoll(); + } + return this.indexedResults[input - 1]; + } + + public getPossibleRewards() { + return this.config.possibleCoinRewards; + } + + public getTags() { + return this.config.tags || []; + } + + public getNotes() { + return this.config.notes; + } + + private getRoll(): number { + let answer: number = 0; + for (let i in this.dice) { + answer = answer + d(this.dice[i]); + } + return answer; + } + + private isValidInput(input: number) { + return typeof this.indexedResults[input - 1] !== 'undefined'; + } + + private constructIndex(coinRewards: CoinRewards[]) { + for (let resultIndex in coinRewards) { + let keys: number[] = coinRewards[resultIndex].keys; + for (let r = Math.min(...keys); r <= Math.max(...keys); r++) { + this.indexedResults.push(coinRewards[resultIndex]); + } + } + } +} + +type ChallengeRating = '0-4' | '5-10' | '11-16' | '17+'; + +interface CoinResult { + type: 'CP' | 'SP' | 'EP' | 'GP' | 'PP'; + count: number; +} + +interface CoinCalc { + type: 'CP' | 'SP' | 'EP' | 'GP' | 'PP'; + rollCount: number; + diceType: number; + multiplier: number; + avg: number; +} + +interface CoinRewards { + keys: number[]; + coinCalc: CoinCalc[]; +} + +interface GemArtCalc { + tableName: string; + rollCount: number; + diceType: number; + avg: number; +} + +interface GemArtResult { + tableName: string; + amount: number; +} + +interface MagicItemCalc { + tableName: string; + rollCount: number; + diceType: number; +} + +interface MagicItemResult { + tableName: string; + numberOfRoles: number; +} + +interface OtherRewards { + keys: number[]; + gemArt: GemArtCalc; + magicItem: MagicItemCalc[]; +} + +interface IndividualTreasureTable { + name: string; + notes?: string; + tags?: string[]; + dice: number[]; + possibleCoinRewards: CoinRewards[]; +} + +interface HoardTresureTable { + name: string; + notes?: string; + tags?: string[]; + dice: number[]; + coinRewards: CoinRewards; + possibleRewards: OtherRewards[] +} + +const treasureService: TreasureService = new TreasureService(); + +export { + HoardTresureTable, + IndividualTreasureTable, + RandomIndividualTreasureTable, + treasureService, +}