| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- import { Inject, Injectable } from "../../Injector/ServiceDecorator";
- import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
- import { FrontworkComponent } from "../../Types/FrontworkComponent";
- import { TableDefiniton, Signup, Raid, Character, RaidData, Spec, SRToken, Item, User } from "../../Types/Types";
- import { IAdmin } from "../../Admin/Interface";
- import { IRaidManager } from "./Interface";
- import { IUserManager } from "../User/Interface";
- import { ICharacterManager } from "../Character/Interface";
- import { _Tiers } from "../../Types/Items";
- import { IItemManager } from "../Item/Interface";
- import { ItemManager } from "../Item/ItemManager";
- import { IPubSub } from "../PubSub/Interface";
-
- @Injectable(IRaidManager)
- export class RaidManager
- implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManager {
- name = "RaidManager" as "RaidManager";
-
- @Inject(IAdmin)
- private admin: IAdmin
-
- @Inject(IUserManager)
- private userManager: IUserManager
-
- @Inject(ICharacterManager)
- private characterManager: ICharacterManager
-
- @Inject(ItemManager)
- private itemManager: IItemManager
-
- @Inject(IPubSub)
- private pubsub: IPubSub<any>
-
- exportRPCs = () => [
- this.getRaids,
- this.getRaidData,
- this.getPastRaids,
- this.getArchiveRaid
- ]
-
- exportRPCFeatures() {
- return [{
- name: 'manageRaid' as 'manageRaid',
- exportRPCs: () => [
- this.createRaid,
- this.addSignup,
- this.removeSignup,
- this.archiveRaid,
- this.setBenched,
- this.startRaid,
- this.adminUnsign
- ]
- }, {
- name: 'signup' as 'signup',
- exportRPCs: () => [
- this.getSignups,
- this.sign,
- this.unsign
- ]
- }]
- }
-
- getTableDefinitions(): TableDefiniton[] {
- return [
- {
- name: 'raids',
- tableBuilder: (table) => {
- table.increments('id').primary()
- table.dateTime('start').notNullable()
- table.string('description').notNullable()
- table.string('title').notNullable()
- table.integer('size').defaultTo(40)
- table.string('tier').defaultTo('null')
- }
- }, {
- name: 'archive',
- tableBuilder: (table) => {
- table.integer('id').primary()
- table.json('raiddata').notNullable()
- }
- }, {
- name: 'signups',
- tableBuilder: (table) => {
- table.increments('id').primary()
- table.unique(['raidid', 'characterid'])
- table.integer('raidid')
- table.foreign('raidid').references('id').inTable('raids').onDelete('CASCADE')
- table.integer('characterid')
- table.foreign('characterid').references('id').inTable('characters').onDelete('CASCADE')
- table.boolean('benched').defaultTo('false')
- table.boolean('late')
- }
- }
- ]
- }
-
- notifyRaid = async (raid:Raid | {id:number}) => {
- const data = await this.getRaidData(<Raid>raid)
- this.pubsub.publish(""+raid.id, data)
- await this.notifyRaids()
- }
-
- notifyRaids = async () => {
- this.pubsub.publish('raids', undefined)
- }
-
- createRaid = async (raid: Raid): Promise<Raid> => {
- const ids: number[] = await this.admin
- .knex('raids')
- .insert(raid)
-
- await this.notifyRaid({ id: ids[0] })
-
- return await this.admin.knex('raids').where({ id: ids[0] }).first()
- }
-
- addSignup = async (signup: Signup) => {
-
- const ids: number[] = await this.admin
- .knex('signups')
- .insert(signup)
- return await this.admin.knex('signups').where({ id: ids[0] }).first()
-
- }
-
- removeSignup = async (signup: Signup) => await this.admin
- .knex('signups')
- .where({
- raid_id: signup.raidid,
- character_id: signup.characterid
- })
- .del()
-
- getRaids = async (): Promise<Raid[]> => {
-
- const subQuery = this.admin
- .knex('signups')
- .count('*')
- .where({
- raidid: this.admin.knex.ref('raids.id'),
- benched: false,
- late: false
- })
- .as('signupcount')
-
- return await this.admin.knex('raids')
- .select('*', subQuery)
- .orderBy('start', 'asc')
- }
-
- startRaid = async (raid: Raid): Promise<RaidData> => {
- const archived = await this.archiveRaid(raid)
-
- const giveCurrency = async (b: Character) => {
- const usr = await this.characterManager.getUserOfCharacter(b)
- await this.userManager.incrementCurrency(usr, raid.tier, 1)
- }
-
- await Promise.all([
- ...archived.participants.bench.map(giveCurrency),
- ...Object.values(archived.participants).flat().flatMap((b:Signup & Character & Spec) => giveCurrency(b))
- ])
-
- await this.notifyRaids()
-
- return archived
- }
-
- archiveRaid = async (raid: Raid): Promise<RaidData> => {
- const raidData = await this.getRaidData(raid)
-
- //const tx = await this.admin.knex.transaction()
-
- await this.admin.knex('archive')
- //.transacting(tx)
- .insert({
- id: raidData.id,
- raiddata: JSON.stringify(raidData)
- })
-
- await Promise.all(
- Object.values(raidData.participants).flat().flatMap((p: (Signup & Character & Spec)) =>
- this.admin
- .knex(raid.tier + 'tokens')
- //.transacting(tx)
- .where({
- characterid: p.characterid,
- signupid: null
- })
- .del()
- ))
-
- await this.admin.knex('raids')
- //.transacting(tx)
- .where('id', '=', raid.id)
- .del()
- //await tx.commit()
-
-
- const row = await this.admin.knex('archive')
- .select('*')
- .where({
- id: raidData.id,
- })
- .first()
- return JSON.parse(row.raiddata)
- }
-
- getArchiveRaid = async (id: number): Promise<RaidData> => {
- const data = await this.admin.knex('archive').select('raiddata').where({
- id: id
- }).first()
-
- return JSON.parse(data.raiddata)
- }
-
- getPastRaids = async (limit: number): Promise<RaidData[]> => {
- const raids = await this.admin.knex('archive')
- .select('*')
- .orderBy('id', 'desc')
- .limit(limit)
-
- return raids.map(raid => JSON.parse(raid.raiddata))
- }
-
- getRaidData = async (raid: Raid): Promise<RaidData> => {
- const raiddata = {
- participants: {
- Druid: <(Signup & Character & Spec)[]>[],
- Hunter: <(Signup & Character & Spec)[]>[],
- Mage: <(Signup & Character & Spec)[]>[],
- Paladin: <(Signup & Character & Spec)[]>[],
- Priest: <(Signup & Character & Spec)[]>[],
- Rogue: <(Signup & Character & Spec)[]>[],
- Shaman: <(Signup & Character & Spec)[]>[],
- Warlock: <(Signup & Character & Spec)[]>[],
- Warrior: <(Signup & Character & Spec)[]>[],
- late: <(Signup & Character & Spec)[]>[],
- bench: <(Signup & Character & Spec)[]>[],
- },
- tokens: {},
- healers: <(Signup & Character & Spec)[]>[],
- tanks: <(Signup & Character & Spec)[]>[]
- }
- //const tx = await this.admin.knex.transaction()
-
- const subQuery = this.admin
- .knex('signups')
- .count('*')
- .where({
- raidid: this.admin.knex.ref('raids.id'),
- benched: false,
- late: false
- })
- .as('signupcount')
-
-
- const raidInDb: Raid = await this.admin.knex('raids')
- .select('*', subQuery)
- //.transacting(tx)
- .where('id', '=', raid.id)
- .first()
-
- const characterData: (Signup & Character & Spec)[] = await this.admin
- .knex('signups as s')
- //.transacting(tx)
- .select('s.id as id', 'charactername', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
- .join('raids as r', 's.raidid', '=', 'r.id')
- .join('characters as c', 's.characterid', '=', 'c.id')
- .join('users as u', 'c.userid', '=', 'u.id')
- .join('specs as sp', 'specid', '=', 'sp.id')
- .where('r.id', '=', raid.id)
-
- characterData.forEach(data => {
- if (data.benched) {
- raiddata.participants.bench.push(data)
- return
- }
- if (data.late) {
- raiddata.participants.late.push(data)
- return
- }
- raiddata.participants[data.class].push(data)
- })
-
- const tokenData: (Character & SRToken & Item)[] = await this.admin
- .knex('signups as s')
- //.transacting(tx)
- .select('*', 's.id as id')
- .join('raids as r', 's.raidid', '=', 'r.id')
- .join('characters as c', 's.characterid', '=', 'c.id')
- .join(raidInDb.tier + 'tokens as t', 't.characterid', '=', 'c.id')
- .join('items as i', 'i.itemname', '=', 't.itemname')
- .where({
- 'r.id': raid.id,
- })
- .andWhere(function () {
- this.whereNotNull('t.signupid')
- })
-
- //await tx.commit()
-
- tokenData.forEach(data => {
- if (!raiddata.tokens[data.itemname])
- raiddata.tokens[data.itemname] = []
- raiddata.tokens[data.itemname].push(data)
- })
-
- raiddata.tanks = Object.values(raiddata.participants).flatMap(
- (tanks: any[]) => tanks.filter((p: any) =>
- !p.benched
- && !p.late
- && (p.specname === "Protection"
- || p.specname === "Feral (Tank)"))
- )
- raiddata.healers = Object.values(raiddata.participants).flatMap(
- (healers: any[]) => healers.filter((p: any) =>
- !p.benched
- && !p.late
- && (p.specname === "Holy"
- || p.specname === "Discipline"
- || p.specname === "Restoration"))
- )
-
- return {
- ...raidInDb,
- ...raiddata
- }
- }
-
- getSignups = async (raid: Raid): Promise<(Signup & Character & Spec & User)[]> => await this.admin
- .knex('signups as si')
- .join('characters as c', 'c.id', '=', 'characterid')
- .join('specs as s', 's.id', '=', 'specid')
- .join('users as u', 'u.id', '=', 'userid')
- .select('*', 'si.id as id')
- .where('raidid', '=', raid.id!)
-
- sign = async (usertoken: string, character: Character, raid: Raid, late: boolean) => {
- const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
- if (!maybeUserRecord || maybeUserRecord.user.id != character.userid) {
- throw new Error("Bad Usertoken")
- }
- //const tx = await this.admin.knex.transaction()
-
- const exists = await this.admin
- .knex('signups')
- //.transacting(tx)
- .select('*')
- .where({
- raidid: raid.id!,
- characterid: character.id!,
- })
- .first()
-
- if (!exists) {
- await this.admin
- .knex('signups')
- //.transacting(tx)
- .insert({
- raidid: raid.id!,
- characterid: character.id!,
- late: late,
- benched: false,
- })
- } else {
- await this.admin
- .knex('signups')
- //.transacting(tx)
- .where({
- id: exists.id
- })
- .update({
- raidid: raid.id!,
- characterid: character.id!,
- late: late,
- benched: false,
- })
- }
- //await tx.commit()
-
- await this.notifyRaid(raid)
-
- return await this.admin
- .knex('signups')
- .select('*')
- .where({
- raidid: raid.id!,
- characterid: character.id!,
- })
- .first()
- }
-
- unsign = async (usertoken: string, character: Character, raid: Raid) => {
- const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
- if (!maybeUserRecord || maybeUserRecord.user.id != character.userid) {
- throw new Error("Bad Usertoken")
- }
-
- return await this.adminUnsign(character, raid)
- }
-
- adminUnsign = async (character: Character, raid: Raid) => {
-
- const user = await this.characterManager.getUserOfCharacter(character)
-
- const signup = await this.admin.knex('signups as si')
- .where({
- "si.raidid": raid.id!,
- "si.characterid": character.id!,
- }).first()
-
- const tokens = await this.itemManager.getTokens(character, [raid.tier], true)
-
- //check if token has to be deleted
- if (tokens) {
- Promise.all(
- tokens.map(async token => {
- await this.userManager.incrementCurrency(user, raid.tier, 1)
- const prio = await this.itemManager.calculatePriorities(token.itemname, character)
- if (token.level <= prio + 1) {
- await this.admin
- .knex(raid.tier + 'tokens')
- .where({
- characterid: character.id,
- itemname: token.itemname
- }).del()
- } else {
- await this.admin
- .knex(raid.tier + 'tokens')
- .where({
- characterid: character.id,
- itemname: token.itemname
- }).update({
- signupid: null,
- level: token.level - 1
- })
- }
- })
- )
- }
-
- await this.admin.knex('signups')
- .where({
- raidid: raid.id!,
- characterid: character.id!,
- })
- .del()
-
- await this.notifyRaid(raid)
- }
-
- setBenched = async (signup: Signup): Promise<void> => {
- await this.admin.knex('signups')
- .where({
- raidid: signup.raidid,
- characterid: signup.characterid
- })
- .update(signup)
-
- await this.notifyRaid({ id: signup.raidid })
- }
- }
|