Browse Source

visual polish and bugfixes. auto-refreshing

master
peter 5 years ago
parent
commit
18f3b32e3c

+ 3
- 3
package-lock.json View File

6130
       }
6130
       }
6131
     },
6131
     },
6132
     "rpclibrary": {
6132
     "rpclibrary": {
6133
-      "version": "1.7.0",
6134
-      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.7.0.tgz",
6135
-      "integrity": "sha512-HIL5YzFF53fACOWvI403hJZnGYoXLJGrGc0n1HYZH6rnnfEaBcogemZrCbyoOvnG204LH882e8VdpB+WBTEY/g==",
6133
+      "version": "1.7.1",
6134
+      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.7.1.tgz",
6135
+      "integrity": "sha512-Ibo3qfURnQgZAq0eA2o+L9+PWaloJ4PHZs4ak42LL9fRgdWZXn33HAtowV0K2HVckbvrBvFqj/+PWTrWWBSOeg==",
6136
       "requires": {
6136
       "requires": {
6137
         "bsock": "^0.1.9",
6137
         "bsock": "^0.1.9",
6138
         "http": "0.0.0",
6138
         "http": "0.0.0",

+ 11
- 10
package.json View File

5
   "scripts": {
5
   "scripts": {
6
     "tsc": "tsc",
6
     "tsc": "tsc",
7
     "launch": "node lib/src/backend/Launcher.js",
7
     "launch": "node lib/src/backend/Launcher.js",
8
-    "start": "npm run build; npm run launch",
9
-    "start-backend": "npm run build-backend; node lib/src/backend/Launcher.js",
10
-    "build": "npm run build-backend; npm run build-frontend",
11
-    "test": "npm run clean && npm run build-backend && mocha lib/test/backendTest.js",
12
-    "build-backend": "tsc;",
13
-    "build-frontend": "mkdir dist; mkdir dist/static; npm run build-dashboard;",
14
-    "build-dashboard": "cd src/frontend; npm i && npm run build; cp -r dist/* ../../dist/static",
15
-    "clean": "rm -rf lib plugins conf widget .rpt2_cache *.js *.ts src/frontend/dist data",
16
-    "update-frontblock": "npm remove frontblock frontblock-generic; npm install frontblock-generic@latest frontblock@latest",
8
+    "start": "npm run build && npm run launch",
9
+    "start-backend": "npm run build-backend && npm run launch",
10
+    "test": "npm run backend && npm run build-backend && mocha lib/test/backendTest.js",
11
+    "build": "npm run build-backend && npm run build-frontend",
12
+    "build-backend": "npm run clean-backend && tsc",
13
+    "build-frontend": "npm run clean-frontend && (mkdir static || rm -rf static/*) && npm run build-dashboard",
14
+    "build-dashboard": "cd src/frontend && npm i && npm run build && cp -r dist/* ../../static",
15
+    "clean": "rm -rf data && npm run clean-backend && npm run clean-frontend",
16
+    "clean-backend": "rm -rf lib plugins config widget .rpt2_cache *.js *.ts",
17
+    "clean-frontend": "rm -rf src/frontend/dist static",
17
     "webpack": "webpack --config src/backend/webpack.prod.js --progress --colors"
18
     "webpack": "webpack --config src/backend/webpack.prod.js --progress --colors"
18
   },
19
   },
19
   "repository": {
20
   "repository": {
44
     "path": "^0.12.7",
45
     "path": "^0.12.7",
45
     "reflect-metadata": "^0.1.13",
46
     "reflect-metadata": "^0.1.13",
46
     "rimraf": "^3.0.0",
47
     "rimraf": "^3.0.0",
47
-    "rpclibrary": "^1.7.0",
48
+    "rpclibrary": "^1.7.1",
48
     "simple-git": "^1.124.0",
49
     "simple-git": "^1.124.0",
49
     "spawn-sync": "^2.0.0",
50
     "spawn-sync": "^2.0.0",
50
     "sqlite3": "^4.1.1",
51
     "sqlite3": "^4.1.1",

+ 8
- 4
src/backend/Admin/Admin.ts View File

20
 import { IAdmin } from './Interface';
20
 import { IAdmin } from './Interface';
21
 import { Injector } from '../Injector/Injector';
21
 import { Injector } from '../Injector/Injector';
22
 import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
22
 import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
23
+import { PubSub } from '../Components/PubSub/PubSub';
23
 
24
 
24
 
25
 
25
 const logger = getLogger("admin", 'debug') 
26
 const logger = getLogger("admin", 'debug') 
32
         RaidManager,
33
         RaidManager,
33
         CharacterManager,
34
         CharacterManager,
34
         UserManager,
35
         UserManager,
35
-        Shoutbox
36
+        Shoutbox,
37
+        PubSub
36
     ]
38
     ]
37
 })
39
 })
38
 export class FrontworkAdmin 
40
 export class FrontworkAdmin 
54
                     dbConf: {
56
                     dbConf: {
55
                         client: 'sqlite3',
57
                         client: 'sqlite3',
56
                         connection: {
58
                         connection: {
57
-                            filename: Path.join(__dirname, "data/frontworkAdmin.sqlite")
59
+                            filename: Path.resolve(__dirname, '../../../..', "data/frontworkAdmin.sqlite")
58
                         },
60
                         },
59
                         useNullAsDefault: true,
61
                         useNullAsDefault: true,
60
                     }
62
                     }
96
     getTableDefinitions(): TableDefiniton[]{
98
     getTableDefinitions(): TableDefiniton[]{
97
         return [
99
         return [
98
             ...this.frontworkComponents
100
             ...this.frontworkComponents
99
-        ].flatMap(exporter => exporter.getTableDefinitions())
101
+        ]
102
+        .filter(exp => exp.getTableDefinitions != null)
103
+        .flatMap(exp => exp.getTableDefinitions())
100
     }
104
     }
101
 
105
 
102
     private startWebsocket(){
106
     private startWebsocket(){
123
         
127
         
124
         let port:number = this.config.getConfig().httpPort
128
         let port:number = this.config.getConfig().httpPort
125
         this.express = express()
129
         this.express = express()
126
-        this.express.use('/', express.static('dist/static'))
130
+        this.express.use('/', express.static('static'))
127
 
131
 
128
         /**
132
         /**
129
          * get the compiled FrontendPlugins.js
133
          * get the compiled FrontendPlugins.js

+ 25
- 4
src/backend/Components/Item/ItemManager.ts View File

1
-import { T1, T2, allItems, _Tiers, Tiers } from "../../Types/Items";
1
+import { allItems, _Tiers, Tiers } from "../../Types/Items";
2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
6
-import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types";
6
+import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup, Raid } from "../../Types/Types";
7
 import { IAdmin } from "../../Admin/Interface";
7
 import { IAdmin } from "../../Admin/Interface";
8
 import { IItemManager } from "./Interface";
8
 import { IItemManager } from "./Interface";
9
 import { getLogger } from "log4js";
9
 import { getLogger } from "log4js";
10
 import { IUserManager } from "../User/Interface";
10
 import { IUserManager } from "../User/Interface";
11
 import { ICharacterManager } from "../Character/Interface";
11
 import { ICharacterManager } from "../Character/Interface";
12
+import { IPubSub } from "../PubSub/Interface";
13
+import { IRaidManager } from "../Raid/Interface";
12
 
14
 
13
 const fetch = require('node-fetch')
15
 const fetch = require('node-fetch')
14
 const xml2js = require('xml2js');
16
 const xml2js = require('xml2js');
28
     @Inject(ICharacterManager)
30
     @Inject(ICharacterManager)
29
     private character: ICharacterManager
31
     private character: ICharacterManager
30
 
32
 
33
+    @Inject(IPubSub)
34
+    private pubsub: IPubSub<any>
35
+
36
+    @Inject(IRaidManager)
37
+    private raidManager: IRaidManager
38
+
31
     exportRPCs = () => [
39
     exportRPCs = () => [
32
         this.getItems,
40
         this.getItems,
33
         this.getItem,
41
         this.getItem,
51
         ]
59
         ]
52
     }]
60
     }]
53
 
61
 
62
+    notifyRaid = async (raid:Raid | {id:number}) => {
63
+        const data = await this.raidManager.getRaidData(<Raid>raid)
64
+        this.pubsub.publish(""+raid.id, data)
65
+        await this.notifyRaids()
66
+    }
67
+
68
+    notifyRaids = async () => {
69
+        this.pubsub.publish('raids', undefined)
70
+    }
71
+
54
     wipeCurrencyAndItems = async () => {
72
     wipeCurrencyAndItems = async () => {
55
         await Promise.all([
73
         await Promise.all([
56
             this.userManager.wipeCurrency(),
74
             this.userManager.wipeCurrency(),
140
 
158
 
141
         await this.userManager.decrementCurrency(record.user, item.tier, 1)
159
         await this.userManager.decrementCurrency(record.user, item.tier, 1)
142
         const modifier = await this.calculatePriorities(itemname, character)
160
         const modifier = await this.calculatePriorities(itemname, character)
143
-
161
+        
144
         const tx = await this.admin.knex.transaction()
162
         const tx = await this.admin.knex.transaction()
145
 
163
 
146
         if(streaks.length > 0){
164
         if(streaks.length > 0){
147
             const myStreak = streaks.find(token => token.itemname === itemname)
165
             const myStreak = streaks.find(token => token.itemname === itemname)
148
             if(myStreak){
166
             if(myStreak){
149
-
150
                 //getLogger('ItemManager').debug('update signupid and increment level')
167
                 //getLogger('ItemManager').debug('update signupid and increment level')
151
                 await this.admin
168
                 await this.admin
152
                 .knex(item.tier+'tokens')
169
                 .knex(item.tier+'tokens')
176
 
193
 
177
             if(myStreak){
194
             if(myStreak){
178
                 await tx.commit()
195
                 await tx.commit()
196
+                await this.notifyRaid({id: signup.raidid})
197
+
179
                 return await this.getToken(character, item)
198
                 return await this.getToken(character, item)
180
             }
199
             }
181
         }
200
         }
205
             })
224
             })
206
         }
225
         }
207
         await tx.commit()
226
         await tx.commit()
227
+        await this.notifyRaid({id: signup.raidid})
228
+
208
         return await this.getToken(character, item)
229
         return await this.getToken(character, item)
209
     }
230
     }
210
 
231
 

+ 7
- 0
src/backend/Components/PubSub/Interface.ts View File

1
+import { SubscriptionResponse } from "rpclibrary"
2
+
3
+export class IPubSub<UpdateType>{
4
+    publish: (topic: string, p: UpdateType) => void
5
+    subscribe: (topic:string, callback: (p:UpdateType)=>any) => Promise<SubscriptionResponse>
6
+    unsubscribe: (uuid: string) => Promise<void>
7
+}

+ 53
- 0
src/backend/Components/PubSub/PubSub.ts View File

1
+import { Injectable } from "../../Injector/ServiceDecorator";
2
+import { SubscriptionResponse, makeSubResponse, RPCExporter } from "rpclibrary";
3
+import { IPubSub } from "./Interface";
4
+
5
+@Injectable(IPubSub)
6
+export class PubSub<UpdateType = any>
7
+implements RPCExporter{
8
+    name = "PubSub"
9
+    subs : {
10
+        [topic in string]: {
11
+            [uuid in string]: (p:UpdateType)=>any
12
+        }
13
+    }= {}
14
+
15
+    exportRPCs = () => [
16
+        this.unsubscribe,
17
+        {
18
+            name: 'subscribe',
19
+            hook: this.subscribe,
20
+            onClose: (subres, rpcName) => {
21
+                this.unsubscribe(subres.uuid)
22
+            }
23
+        }
24
+    ]
25
+
26
+    publish = ( topic: string, msg: UpdateType ) => {
27
+        if(!this.subs[topic]) this.subs[topic] = {}
28
+        Object.entries(this.subs[topic]).forEach(([uuid, callback]:[string, Function]) => {
29
+            try{
30
+                callback(msg)
31
+            }catch(e){
32
+                delete this.subs[topic][uuid]
33
+            }
34
+        })
35
+    }
36
+
37
+    subscribe = async (topic:string, callback:(p:UpdateType)=>any) : Promise<SubscriptionResponse<{topic: string}>> => {
38
+        const resp = makeSubResponse({
39
+            topic: topic
40
+        })
41
+        if(!this.subs[topic]) this.subs[topic] = {}
42
+        this.subs[topic][resp.uuid] = callback
43
+        return resp
44
+    }
45
+
46
+    private unsubscribe = async (uuid: string) => {
47
+        Object.entries(this.subs).forEach(([topic, submap]) => {           
48
+            delete submap[uuid]
49
+            if(Object.keys(submap).length === 0)
50
+                delete this.subs[topic]
51
+        })
52
+    }
53
+}

+ 8
- 0
src/backend/Components/PubSub/RPCInterface.ts View File

1
+import { IPubSub } from "./Interface";
2
+
3
+export type PubSubIfc<UpdateType = any> = {
4
+    PubSub:{
5
+        subscribe: IPubSub<UpdateType>['subscribe']
6
+        unsubscribe: IPubSub<UpdateType>['unsubscribe']
7
+    }
8
+}

+ 242
- 214
src/backend/Components/Raid/RaidManager.ts View File

9
 import { _Tiers } from "../../Types/Items";
9
 import { _Tiers } from "../../Types/Items";
10
 import { IItemManager } from "../Item/Interface";
10
 import { IItemManager } from "../Item/Interface";
11
 import { ItemManager } from "../Item/ItemManager";
11
 import { ItemManager } from "../Item/ItemManager";
12
+import { IPubSub } from "../PubSub/Interface";
12
 
13
 
13
 @Injectable(IRaidManager)
14
 @Injectable(IRaidManager)
14
 export class RaidManager
15
 export class RaidManager
15
-implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManager{
16
-    name = "RaidManager" as "RaidManager";    
16
+    implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManager {
17
+    name = "RaidManager" as "RaidManager";
17
 
18
 
18
     @Inject(IAdmin)
19
     @Inject(IAdmin)
19
     private admin: IAdmin
20
     private admin: IAdmin
27
     @Inject(ItemManager)
28
     @Inject(ItemManager)
28
     private itemManager: IItemManager
29
     private itemManager: IItemManager
29
 
30
 
31
+    @Inject(IPubSub)
32
+    private pubsub: IPubSub<any>
33
+
30
     exportRPCs = () => [
34
     exportRPCs = () => [
31
         this.getRaids,
35
         this.getRaids,
32
         this.getRaidData,
36
         this.getRaidData,
46
                 this.startRaid,
50
                 this.startRaid,
47
                 this.adminUnsign
51
                 this.adminUnsign
48
             ]
52
             ]
49
-        },{
53
+        }, {
50
             name: 'signup' as 'signup',
54
             name: 'signup' as 'signup',
51
             exportRPCs: () => [
55
             exportRPCs: () => [
52
                 this.getSignups,
56
                 this.getSignups,
55
             ]
59
             ]
56
         }]
60
         }]
57
     }
61
     }
58
-    
62
+
59
     getTableDefinitions(): TableDefiniton[] {
63
     getTableDefinitions(): TableDefiniton[] {
60
         return [
64
         return [
61
             {
65
             {
68
                     table.integer('size').defaultTo(40)
72
                     table.integer('size').defaultTo(40)
69
                     table.string('tier').defaultTo('null')
73
                     table.string('tier').defaultTo('null')
70
                 }
74
                 }
71
-            },{
75
+            }, {
72
                 name: 'archive',
76
                 name: 'archive',
73
                 tableBuilder: (table) => {
77
                 tableBuilder: (table) => {
74
                     table.integer('id').primary()
78
                     table.integer('id').primary()
75
                     table.json('raiddata').notNullable()
79
                     table.json('raiddata').notNullable()
76
                 }
80
                 }
77
-            },{
81
+            }, {
78
                 name: 'signups',
82
                 name: 'signups',
79
                 tableBuilder: (table) => {
83
                 tableBuilder: (table) => {
80
                     table.increments('id').primary()
84
                     table.increments('id').primary()
86
                     table.boolean('benched').defaultTo('false')
90
                     table.boolean('benched').defaultTo('false')
87
                     table.boolean('late')
91
                     table.boolean('late')
88
                 }
92
                 }
89
-            }            
93
+            }
90
         ]
94
         ]
91
     }
95
     }
92
 
96
 
93
-    createRaid = async (raid:Raid) : Promise<Raid>=> {
94
-        const ids:number[] = await this.admin
95
-        .knex('raids')
96
-        .insert(raid)
97
+    notifyRaid = async (raid:Raid | {id:number}) => {
98
+        const data = await this.getRaidData(<Raid>raid)
99
+        this.pubsub.publish(""+raid.id, data)
100
+        await this.notifyRaids()
101
+    }
97
 
102
 
98
-        return await this.admin.knex('raids').where({id: ids[0]}).first()
103
+    notifyRaids = async () => {
104
+        this.pubsub.publish('raids', undefined)
99
     }
105
     }
100
 
106
 
101
-    addSignup = async (signup: Signup) => {
107
+    createRaid = async (raid: Raid): Promise<Raid> => {
108
+        const ids: number[] = await this.admin
109
+            .knex('raids')
110
+            .insert(raid)
102
 
111
 
103
-        const ids:number[] = await this.admin
104
-        .knex('signups')
105
-        .insert(signup)
106
-        return await this.admin.knex('signups').where({id: ids[0]}).first()
112
+        await this.notifyRaid({ id: ids[0] })
107
 
113
 
114
+        return await this.admin.knex('raids').where({ id: ids[0] }).first()
108
     }
115
     }
109
 
116
 
110
-    removeSignup = async (signup: Signup) => await this.admin
111
-    .knex('signups')
112
-    .where({
113
-        raid_id: signup.raidid, 
114
-        character_id: signup.characterid
115
-    })
116
-    .del()
117
+    addSignup = async (signup: Signup) => {
117
 
118
 
118
-    getRaids = async () : Promise<Raid[]> => {
119
+        const ids: number[] = await this.admin
120
+            .knex('signups')
121
+            .insert(signup)
122
+        return await this.admin.knex('signups').where({ id: ids[0] }).first()
119
 
123
 
120
-        const subQuery = this.admin
124
+    }
125
+
126
+    removeSignup = async (signup: Signup) => await this.admin
121
         .knex('signups')
127
         .knex('signups')
122
-        .count('*')
123
         .where({
128
         .where({
124
-            raidid: this.admin.knex.ref('raids.id'),
125
-            benched: false,
126
-            late: false
129
+            raid_id: signup.raidid,
130
+            character_id: signup.characterid
127
         })
131
         })
128
-        .as('signupcount')
129
-        
132
+        .del()
133
+
134
+    getRaids = async (): Promise<Raid[]> => {
135
+
136
+        const subQuery = this.admin
137
+            .knex('signups')
138
+            .count('*')
139
+            .where({
140
+                raidid: this.admin.knex.ref('raids.id'),
141
+                benched: false,
142
+                late: false
143
+            })
144
+            .as('signupcount')
145
+
130
         return await this.admin.knex('raids')
146
         return await this.admin.knex('raids')
131
-        .select('*', subQuery)
132
-        .orderBy('start', 'asc')
147
+            .select('*', subQuery)
148
+            .orderBy('start', 'asc')
133
     }
149
     }
134
 
150
 
135
-    startRaid = async (raid:Raid) : Promise<RaidData> => {
151
+    startRaid = async (raid: Raid): Promise<RaidData> => {
136
         const archived = await this.archiveRaid(raid)
152
         const archived = await this.archiveRaid(raid)
137
-        
153
+
138
         const giveCurrency = async (b: Character) => {
154
         const giveCurrency = async (b: Character) => {
139
             const usr = await this.characterManager.getUserOfCharacter(b)
155
             const usr = await this.characterManager.getUserOfCharacter(b)
140
             await this.userManager.incrementCurrency(usr, raid.tier, 1)
156
             await this.userManager.incrementCurrency(usr, raid.tier, 1)
142
 
158
 
143
         await Promise.all([
159
         await Promise.all([
144
             ...archived.participants.bench.map(giveCurrency),
160
             ...archived.participants.bench.map(giveCurrency),
145
-            ...Object.values(archived.participants).map((group: any) => group.map(giveCurrency))
161
+            ...Object.values(archived.participants).flat().flatMap((b:Signup & Character & Spec) => giveCurrency(b))
146
         ])
162
         ])
147
 
163
 
164
+        await this.notifyRaids()
165
+
148
         return archived
166
         return archived
149
     }
167
     }
150
 
168
 
151
-    archiveRaid = async (raid:Raid) : Promise<RaidData> => {
169
+    archiveRaid = async (raid: Raid): Promise<RaidData> => {
152
         const raidData = await this.getRaidData(raid)
170
         const raidData = await this.getRaidData(raid)
153
 
171
 
154
         //const tx = await this.admin.knex.transaction()
172
         //const tx = await this.admin.knex.transaction()
155
 
173
 
156
         await this.admin.knex('archive')
174
         await this.admin.knex('archive')
157
-        //.transacting(tx)
158
-        .insert({
159
-            id:raidData.id,
160
-            raiddata: JSON.stringify(raidData)
161
-        })       
175
+            //.transacting(tx)
176
+            .insert({
177
+                id: raidData.id,
178
+                raiddata: JSON.stringify(raidData)
179
+            })
162
 
180
 
163
         await Promise.all(
181
         await Promise.all(
164
-            Object.values(raidData.participants).flat().flatMap((signup) => this.admin
165
-                .knex(raid.tier+'tokens')
182
+            Object.values(raidData.participants).flat().flatMap((p: (Signup & Character & Spec)) => 
183
+                this.admin
184
+                .knex(raid.tier + 'tokens')
166
                 //.transacting(tx)
185
                 //.transacting(tx)
167
                 .where({
186
                 .where({
168
-                    characterid: signup.characterid,
187
+                    characterid: p.characterid,
169
                     signupid: null
188
                     signupid: null
170
                 })
189
                 })
171
                 .del()
190
                 .del()
172
-        ))
191
+            ))
173
 
192
 
174
         await this.admin.knex('raids')
193
         await this.admin.knex('raids')
175
-        //.transacting(tx)
176
-        .where('id', '=', raid.id)
177
-        .del()
194
+            //.transacting(tx)
195
+            .where('id', '=', raid.id)
196
+            .del()
178
         //await tx.commit()
197
         //await tx.commit()
179
 
198
 
180
-    
199
+
181
         const row = await this.admin.knex('archive')
200
         const row = await this.admin.knex('archive')
182
-        .select('*')
183
-        .where({
184
-            id:raidData.id,
185
-        })
186
-        .first()
201
+            .select('*')
202
+            .where({
203
+                id: raidData.id,
204
+            })
205
+            .first()
187
         return JSON.parse(row.raiddata)
206
         return JSON.parse(row.raiddata)
188
     }
207
     }
189
 
208
 
190
-    getArchiveRaid = async(id:number) : Promise<RaidData> => {
209
+    getArchiveRaid = async (id: number): Promise<RaidData> => {
191
         const data = await this.admin.knex('archive').select('raiddata').where({
210
         const data = await this.admin.knex('archive').select('raiddata').where({
192
             id: id
211
             id: id
193
         }).first()
212
         }).first()
194
-        
213
+
195
         return JSON.parse(data.raiddata)
214
         return JSON.parse(data.raiddata)
196
     }
215
     }
197
 
216
 
198
-    getPastRaids = async(limit: number) : Promise<RaidData[]> => {
217
+    getPastRaids = async (limit: number): Promise<RaidData[]> => {
199
         const raids = await this.admin.knex('archive')
218
         const raids = await this.admin.knex('archive')
200
-        .select('*')
201
-        .orderBy('id', 'desc')
202
-        .limit(limit)
219
+            .select('*')
220
+            .orderBy('id', 'desc')
221
+            .limit(limit)
203
 
222
 
204
         return raids.map(raid => JSON.parse(raid.raiddata))
223
         return raids.map(raid => JSON.parse(raid.raiddata))
205
     }
224
     }
206
 
225
 
207
-    getRaidData = async (raid:Raid) : Promise<RaidData> => {
226
+    getRaidData = async (raid: Raid): Promise<RaidData> => {
208
         const raiddata = {
227
         const raiddata = {
209
-            participants:{
210
-                Druid: <(Signup&Character&Spec)[]>[],
211
-                Hunter: <(Signup&Character&Spec)[]>[],
212
-                Mage: <(Signup&Character&Spec)[]>[],
213
-                Paladin: <(Signup&Character&Spec)[]>[],
214
-                Priest: <(Signup&Character&Spec)[]>[],
215
-                Rogue: <(Signup&Character&Spec)[]>[],
216
-                Shaman: <(Signup&Character&Spec)[]>[],
217
-                Warlock: <(Signup&Character&Spec)[]>[],
218
-                Warrior: <(Signup&Character&Spec)[]>[],
219
-                late: <(Signup&Character&Spec)[]>[],
220
-                bench: <(Signup&Character&Spec)[]>[],
228
+            participants: {
229
+                Druid: <(Signup & Character & Spec)[]>[],
230
+                Hunter: <(Signup & Character & Spec)[]>[],
231
+                Mage: <(Signup & Character & Spec)[]>[],
232
+                Paladin: <(Signup & Character & Spec)[]>[],
233
+                Priest: <(Signup & Character & Spec)[]>[],
234
+                Rogue: <(Signup & Character & Spec)[]>[],
235
+                Shaman: <(Signup & Character & Spec)[]>[],
236
+                Warlock: <(Signup & Character & Spec)[]>[],
237
+                Warrior: <(Signup & Character & Spec)[]>[],
238
+                late: <(Signup & Character & Spec)[]>[],
239
+                bench: <(Signup & Character & Spec)[]>[],
221
             },
240
             },
222
-            tokens:{},
223
-            healers:<(Signup&Character&Spec)[]>[],
224
-            tanks:<(Signup&Character&Spec)[]>[]
241
+            tokens: {},
242
+            healers: <(Signup & Character & Spec)[]>[],
243
+            tanks: <(Signup & Character & Spec)[]>[]
225
         }
244
         }
226
         //const tx = await this.admin.knex.transaction()
245
         //const tx = await this.admin.knex.transaction()
227
 
246
 
228
         const subQuery = this.admin
247
         const subQuery = this.admin
229
-        .knex('signups')
230
-        .count('*')
231
-        .where({
232
-            raidid: this.admin.knex.ref('raids.id'),
233
-            benched: false,
234
-            late: false
235
-        })
236
-        .as('signupcount')
248
+            .knex('signups')
249
+            .count('*')
250
+            .where({
251
+                raidid: this.admin.knex.ref('raids.id'),
252
+                benched: false,
253
+                late: false
254
+            })
255
+            .as('signupcount')
237
 
256
 
238
 
257
 
239
         const raidInDb: Raid = await this.admin.knex('raids')
258
         const raidInDb: Raid = await this.admin.knex('raids')
240
-        .select('*', subQuery)
241
-        //.transacting(tx)
242
-        .where('id','=',raid.id)
243
-        .first()
259
+            .select('*', subQuery)
260
+            //.transacting(tx)
261
+            .where('id', '=', raid.id)
262
+            .first()
244
 
263
 
245
         const characterData: (Signup & Character & Spec)[] = await this.admin
264
         const characterData: (Signup & Character & Spec)[] = await this.admin
246
-        .knex('signups as s')
247
-        //.transacting(tx)
248
-        .select('s.id as id', 'charactername', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
249
-        .join('raids as r', 's.raidid','=','r.id')
250
-        .join('characters as c', 's.characterid','=','c.id')
251
-        .join('users as u', 'c.userid','=','u.id')
252
-        .join('specs as sp', 'specid','=','sp.id')
253
-        .where('r.id','=',raid.id)
254
-        
265
+            .knex('signups as s')
266
+            //.transacting(tx)
267
+            .select('s.id as id', 'charactername', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
268
+            .join('raids as r', 's.raidid', '=', 'r.id')
269
+            .join('characters as c', 's.characterid', '=', 'c.id')
270
+            .join('users as u', 'c.userid', '=', 'u.id')
271
+            .join('specs as sp', 'specid', '=', 'sp.id')
272
+            .where('r.id', '=', raid.id)
273
+
255
         characterData.forEach(data => {
274
         characterData.forEach(data => {
256
-            if(data.benched){
275
+            if (data.benched) {
257
                 raiddata.participants.bench.push(data)
276
                 raiddata.participants.bench.push(data)
258
                 return
277
                 return
259
             }
278
             }
260
-            if(data.late){
279
+            if (data.late) {
261
                 raiddata.participants.late.push(data)
280
                 raiddata.participants.late.push(data)
262
                 return
281
                 return
263
             }
282
             }
265
         })
284
         })
266
 
285
 
267
         const tokenData: (Character & SRToken & Item)[] = await this.admin
286
         const tokenData: (Character & SRToken & Item)[] = await this.admin
268
-        .knex('signups as s')
269
-        //.transacting(tx)
270
-        .select('*', 's.id as id')
271
-        .join('raids as r', 's.raidid','=','r.id')
272
-        .join('characters as c', 's.characterid','=','c.id')
273
-        .join(raidInDb.tier+'tokens as t', 't.characterid','=','c.id')
274
-        .join('items as i', 'i.itemname','=','t.itemname')
275
-        .where({
276
-            'r.id': raid.id,
277
-        })
278
-        .andWhere(function(){
279
-            this.whereNotNull('t.signupid')
280
-        })
287
+            .knex('signups as s')
288
+            //.transacting(tx)
289
+            .select('*', 's.id as id')
290
+            .join('raids as r', 's.raidid', '=', 'r.id')
291
+            .join('characters as c', 's.characterid', '=', 'c.id')
292
+            .join(raidInDb.tier + 'tokens as t', 't.characterid', '=', 'c.id')
293
+            .join('items as i', 'i.itemname', '=', 't.itemname')
294
+            .where({
295
+                'r.id': raid.id,
296
+            })
297
+            .andWhere(function () {
298
+                this.whereNotNull('t.signupid')
299
+            })
281
 
300
 
282
         //await tx.commit()
301
         //await tx.commit()
283
 
302
 
284
         tokenData.forEach(data => {
303
         tokenData.forEach(data => {
285
-            if(!raiddata.tokens[data.itemname])
304
+            if (!raiddata.tokens[data.itemname])
286
                 raiddata.tokens[data.itemname] = []
305
                 raiddata.tokens[data.itemname] = []
287
             raiddata.tokens[data.itemname].push(data)
306
             raiddata.tokens[data.itemname].push(data)
288
         })
307
         })
289
 
308
 
290
         raiddata.tanks = Object.values(raiddata.participants).flatMap(
309
         raiddata.tanks = Object.values(raiddata.participants).flatMap(
291
-            (tanks:any[]) => tanks.filter((p:any) => 
292
-                !p.benched 
293
-                && !p.late 
294
-                && (p.specname==="Protection" 
295
-                    || p.specname==="Feral (Tank)"))
310
+            (tanks: any[]) => tanks.filter((p: any) =>
311
+                !p.benched
312
+                && !p.late
313
+                && (p.specname === "Protection"
314
+                    || p.specname === "Feral (Tank)"))
296
         )
315
         )
297
         raiddata.healers = Object.values(raiddata.participants).flatMap(
316
         raiddata.healers = Object.values(raiddata.participants).flatMap(
298
-            (healers:any[]) => healers.filter((p:any) => 
299
-                !p.benched 
300
-                && !p.late 
301
-                && (p.specname==="Holy" 
302
-                    || p.specname==="Discipline" 
303
-                    || p.specname==="Restoration"))
317
+            (healers: any[]) => healers.filter((p: any) =>
318
+                !p.benched
319
+                && !p.late
320
+                && (p.specname === "Holy"
321
+                    || p.specname === "Discipline"
322
+                    || p.specname === "Restoration"))
304
         )
323
         )
305
 
324
 
306
         return {
325
         return {
308
             ...raiddata
327
             ...raiddata
309
         }
328
         }
310
     }
329
     }
311
-    
312
-    getSignups = async (raid:Raid) : Promise<(Signup & Character & Spec & User)[]> => await this.admin
313
-    .knex('signups as si')
314
-    .join('characters as c', 'c.id', '=', 'characterid')
315
-    .join('specs as s', 's.id', '=', 'specid')
316
-    .join('users as u', 'u.id', '=', 'userid')
317
-    .select('*','si.id as id')
318
-    .where('raidid', '=', raid.id!)
319
-    
320
-    sign = async (usertoken:string, character:Character, raid:Raid, late:boolean) => {
330
+
331
+    getSignups = async (raid: Raid): Promise<(Signup & Character & Spec & User)[]> => await this.admin
332
+        .knex('signups as si')
333
+        .join('characters as c', 'c.id', '=', 'characterid')
334
+        .join('specs as s', 's.id', '=', 'specid')
335
+        .join('users as u', 'u.id', '=', 'userid')
336
+        .select('*', 'si.id as id')
337
+        .where('raidid', '=', raid.id!)
338
+
339
+    sign = async (usertoken: string, character: Character, raid: Raid, late: boolean) => {
321
         const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
340
         const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
322
-        if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
341
+        if (!maybeUserRecord || maybeUserRecord.user.id != character.userid) {
323
             throw new Error("Bad Usertoken")
342
             throw new Error("Bad Usertoken")
324
         }
343
         }
325
         //const tx = await this.admin.knex.transaction()
344
         //const tx = await this.admin.knex.transaction()
326
 
345
 
327
         const exists = await this.admin
346
         const exists = await this.admin
328
-        .knex('signups')
329
-        //.transacting(tx)
330
-        .select('*')
331
-        .where({
332
-            raidid: raid.id!,
333
-            characterid: character.id!,
334
-        })
335
-        .first()
336
-
337
-        if(!exists){
338
-            await this.admin
339
             .knex('signups')
347
             .knex('signups')
340
             //.transacting(tx)
348
             //.transacting(tx)
341
-            .insert({
349
+            .select('*')
350
+            .where({
342
                 raidid: raid.id!,
351
                 raidid: raid.id!,
343
                 characterid: character.id!,
352
                 characterid: character.id!,
344
-                late: late,
345
-                benched: false,
346
             })
353
             })
347
-        }else{
354
+            .first()
355
+
356
+        if (!exists) {
357
+            await this.admin
358
+                .knex('signups')
359
+                //.transacting(tx)
360
+                .insert({
361
+                    raidid: raid.id!,
362
+                    characterid: character.id!,
363
+                    late: late,
364
+                    benched: false,
365
+                })
366
+        } else {
348
             await this.admin
367
             await this.admin
368
+                .knex('signups')
369
+                //.transacting(tx)
370
+                .where({
371
+                    id: exists.id
372
+                })
373
+                .update({
374
+                    raidid: raid.id!,
375
+                    characterid: character.id!,
376
+                    late: late,
377
+                    benched: false,
378
+                })
379
+        }
380
+        //await tx.commit()
381
+
382
+        await this.notifyRaid(raid)
383
+        
384
+        return await this.admin
349
             .knex('signups')
385
             .knex('signups')
350
-            //.transacting(tx)
386
+            .select('*')
351
             .where({
387
             .where({
352
-                id: exists.id 
353
-            })
354
-            .update({
355
                 raidid: raid.id!,
388
                 raidid: raid.id!,
356
                 characterid: character.id!,
389
                 characterid: character.id!,
357
-                late: late,
358
-                benched: false,
359
             })
390
             })
360
-        }
361
-        //await tx.commit()
362
-
363
-        return await this.admin
364
-        .knex('signups')
365
-        .select('*')
366
-        .where({
367
-            raidid: raid.id!,
368
-            characterid: character.id!,
369
-        })
370
-        .first()
391
+            .first()
371
     }
392
     }
372
 
393
 
373
-    unsign = async (usertoken:string, character:Character, raid:Raid) => {
394
+    unsign = async (usertoken: string, character: Character, raid: Raid) => {
374
         const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
395
         const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
375
-        if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
396
+        if (!maybeUserRecord || maybeUserRecord.user.id != character.userid) {
376
             throw new Error("Bad Usertoken")
397
             throw new Error("Bad Usertoken")
377
         }
398
         }
378
 
399
 
379
-        return await this.adminUnsign(character, raid)       
400
+        return await this.adminUnsign(character, raid)
380
     }
401
     }
381
 
402
 
382
-    adminUnsign = async (character:Character, raid:Raid) => {
383
-        
403
+    adminUnsign = async (character: Character, raid: Raid) => {
404
+
384
         const user = await this.characterManager.getUserOfCharacter(character)
405
         const user = await this.characterManager.getUserOfCharacter(character)
385
 
406
 
386
         const signup = await this.admin.knex('signups as si')
407
         const signup = await this.admin.knex('signups as si')
387
-        .where({
388
-            "si.raidid": raid.id!,
389
-            "si.characterid": character.id!,
390
-        }).first()
408
+            .where({
409
+                "si.raidid": raid.id!,
410
+                "si.characterid": character.id!,
411
+            }).first()
412
+
413
+        const tokens = await this.itemManager.getTokens(character, [raid.tier], true)
391
 
414
 
392
-        const tokens = await this.admin.knex(raid.tier+'tokens as t')
393
-        .where('t.signupid', signup.id)
394
-        
395
         //check if token has to be deleted
415
         //check if token has to be deleted
396
-        Promise.all(
397
-            tokens.map(async token => {
398
-                await this.userManager.incrementCurrency(user, raid.tier, 1)       
399
-                const prio = await this.itemManager.calculatePriorities(token.itemname, character)
400
-                if(token.level <= prio+1){
401
-                    await this.admin.knex(raid.tier+'tokens')
402
-                    .where({
403
-                        characterid: character.id,
404
-                        itemname: token.itemname
405
-                    }).del()
406
-                }else{
407
-                    await this.admin.knex(raid.tier+'tokens')
408
-                    .where({
409
-                        characterid: character.id,
410
-                        itemname: token.itemname
411
-                    }).update({
412
-                        signupid: null,
413
-                        level: token.level-1
414
-                    })
415
-                }
416
-            })
417
-        )
416
+        if (tokens) {
417
+            Promise.all(
418
+                tokens.map(async token => {
419
+                    await this.userManager.incrementCurrency(user, raid.tier, 1)
420
+                    const prio = await this.itemManager.calculatePriorities(token.itemname, character)
421
+                    if (token.level <= prio + 1) {
422
+                        await this.admin
423
+                            .knex(raid.tier + 'tokens')
424
+                            .where({
425
+                                characterid: character.id,
426
+                                itemname: token.itemname
427
+                            }).del()
428
+                    } else {
429
+                        await this.admin
430
+                            .knex(raid.tier + 'tokens')
431
+                            .where({
432
+                                characterid: character.id,
433
+                                itemname: token.itemname
434
+                            }).update({
435
+                                signupid: null,
436
+                                level: token.level - 1
437
+                            })
438
+                    }
439
+                })
440
+            )
441
+        }
418
 
442
 
419
         await this.admin.knex('signups')
443
         await this.admin.knex('signups')
420
-        .where({
421
-            raidid: raid.id!,
422
-            characterid: character.id!,
423
-        })
424
-        .del()
444
+            .where({
445
+                raidid: raid.id!,
446
+                characterid: character.id!,
447
+            })
448
+            .del()
449
+
450
+        await this.notifyRaid(raid)
425
     }
451
     }
426
 
452
 
427
-    setBenched = async (signup: Signup) : Promise<void> => {
453
+    setBenched = async (signup: Signup): Promise<void> => {
428
         await this.admin.knex('signups')
454
         await this.admin.knex('signups')
429
-        .where({
430
-            raidid: signup.raidid,
431
-            characterid: signup.characterid
432
-        })
433
-        .update(signup)
455
+            .where({
456
+                raidid: signup.raidid,
457
+                characterid: signup.characterid
458
+            })
459
+            .update(signup)
460
+    
461
+        await this.notifyRaid({ id: signup.raidid })
434
     }
462
     }
435
 }
463
 }

+ 0
- 2
src/backend/Components/User/UserManager.ts View File

455
         .where('id', '=', user.id)
455
         .where('id', '=', user.id)
456
         .update(tier, value)
456
         .update(tier, value)
457
     }
457
     }
458
-
459
-
460
 }
458
 }

+ 2
- 1
src/backend/Injector/ServiceDecorator.ts View File

1
 import { Injector } from "./Injector";
1
 import { Injector } from "./Injector";
2
 import { Type, GenericClassDecorator } from "./Util";
2
 import { Type, GenericClassDecorator } from "./Util";
3
 import { FrontworkComponent } from "../Types/FrontworkComponent";
3
 import { FrontworkComponent } from "../Types/FrontworkComponent";
4
+import { RPCExporter } from "rpclibrary";
4
 
5
 
5
 /**
6
 /**
6
  * @returns {GenericClassDecorator<Type<any>>}
7
  * @returns {GenericClassDecorator<Type<any>>}
21
  */
22
  */
22
 export const RootComponent = (config : {
23
 export const RootComponent = (config : {
23
     injectable : Type<any>
24
     injectable : Type<any>
24
-    injects : Type<FrontworkComponent>[]
25
+    injects : Type<RPCExporter>[]
25
   }) : GenericClassDecorator<Type<any>> => {
26
   }) : GenericClassDecorator<Type<any>> => {
26
   return (target: Type<any>) => {
27
   return (target: Type<any>) => {
27
     Injector.rootModules = config.injects
28
     Injector.rootModules = config.injects

+ 2
- 0
src/backend/Types/Types.ts View File

7
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
7
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
8
 import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
8
 import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
9
 import { Tiers } from "./Items";
9
 import { Tiers } from "./Items";
10
+import { PubSubIfc } from "../Components/PubSub/RPCInterface";
10
 
11
 
11
 export type FrontcraftIfc = RaidManagerIfc
12
 export type FrontcraftIfc = RaidManagerIfc
12
                           & UserManagerIfc
13
                           & UserManagerIfc
14
                           & ItemManagerIfc
15
                           & ItemManagerIfc
15
                           & GuildManagerIfc
16
                           & GuildManagerIfc
16
                           & ShoutboxIfc
17
                           & ShoutboxIfc
18
+                          & PubSubIfc
17
 
19
 
18
 export type FrontcraftFeatureIfc = RaidManagerFeatureIfc 
20
 export type FrontcraftFeatureIfc = RaidManagerFeatureIfc 
19
                                  & UserManagerFeatureIfc
21
                                  & UserManagerFeatureIfc

+ 3
- 3
src/frontend/package-lock.json View File

14269
       "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
14269
       "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
14270
     },
14270
     },
14271
     "rpclibrary": {
14271
     "rpclibrary": {
14272
-      "version": "1.6.2",
14273
-      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.6.2.tgz",
14274
-      "integrity": "sha512-lQTU4XkB9CSHz7YgtAcpVfyR5XrmTRX4P4eQjK6DDUjqKSFvJb5ChXjHnt1BcaNWbJ2VqmhCNVbcoyunJ2u7Rg==",
14272
+      "version": "1.7.1",
14273
+      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.7.1.tgz",
14274
+      "integrity": "sha512-Ibo3qfURnQgZAq0eA2o+L9+PWaloJ4PHZs4ak42LL9fRgdWZXn33HAtowV0K2HVckbvrBvFqj/+PWTrWWBSOeg==",
14275
       "requires": {
14275
       "requires": {
14276
         "bsock": "^0.1.9",
14276
         "bsock": "^0.1.9",
14277
         "http": "0.0.0",
14277
         "http": "0.0.0",

+ 1
- 1
src/frontend/package.json View File

69
     "normalize.css": "6.0.0",
69
     "normalize.css": "6.0.0",
70
     "pace-js": "1.0.2",
70
     "pace-js": "1.0.2",
71
     "roboto-fontface": "0.8.0",
71
     "roboto-fontface": "0.8.0",
72
-    "rpclibrary": "^1.6.2",
72
+    "rpclibrary": "^1.7.1",
73
     "rxjs": "6.5.2",
73
     "rxjs": "6.5.2",
74
     "rxjs-compat": "6.3.0",
74
     "rxjs-compat": "6.3.0",
75
     "socicon": "3.0.5",
75
     "socicon": "3.0.5",

+ 161
- 202
src/frontend/src/app/frontcraft/pages/raid/raid.component.html View File

1
-<nb-card class="col-12 col-xl-9">
2
-    <nb-card-body>
3
-        <nb-tabset>
4
-            <nb-tab tabTitle="Info">
5
-                <h1>          
6
-                    <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" style="height: 100px" />
7
-                    {{raid.title}}
8
-                </h1>
9
-                <p>
10
-                    {{raid.signupcount}} / {{raid.size}} signups
11
-                </p>
12
-                <p>
13
-                    {{raid.description}}
14
-                </p>
15
-                <div *ngIf="canSignup">
16
-                    <div *ngIf="isSignedup">
17
-
1
+<div class="row">
2
+    <div class="col-12 col-xl-6">
3
+        <nb-card  [size]="giant">
4
+            <nb-card-body>
5
+                <nb-tabset>
6
+                    <nb-tab tabTitle="Info">
7
+                        <h1>
8
+                            <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
9
+                                style="height: 100px" />
10
+                            {{raid.title}}
11
+                        </h1>
12
+                        <p>
13
+                            {{raid.signupcount}} / {{raid.size}} signups
14
+                        </p>
18
                         <p>
15
                         <p>
19
-                            You are signed as: {{mySignup.charactername}} ({{mySignup.race}} {{mySignup.specname}} {{mySignup.class}})<br />
20
-                            Status: {{mySignup.status}}
16
+                            {{raid.description}}
21
                         </p>
17
                         </p>
22
-                        
23
-                        <button
24
-                            (click)="setLate(true)"
25
-                            *ngIf="mySignup.status !== 'Late'"
26
-                            nbButton 
27
-                            outline 
28
-                            status="warning" 
29
-                            size="medium">
30
-                            <nb-icon icon="clock-outline"></nb-icon> Late
31
-                        </button>        
32
-                        <button
33
-                            (click)="setLate(false)"
34
-                            *ngIf="mySignup.status === 'Late'"
35
-                            nbButton 
36
-                            outline 
37
-                            status="success" 
38
-                            size="medium">
39
-                            <nb-icon icon="checkmark-outline"></nb-icon> On Time
40
-                        </button>  
41
-                        <button
42
-                            (click)="unsign()"
43
-                            nbButton 
44
-                            outline 
45
-                            status="danger" 
46
-                            size="medium">
47
-                            <nb-icon icon="close"></nb-icon>unsign
48
-                        </button>               
49
-                    </div>
50
-                    <div *ngIf="!isSignedup">
51
-                        <button
52
-                            (click)="signup()"
53
-                            nbButton 
54
-                            outline 
55
-                            status="success" 
56
-                            size="medium">
57
-                            <nb-icon icon="person-done-outline"></nb-icon> sign up
58
-                        </button>                     
59
-                    </div>
60
-                </div>
61
-            </nb-tab>
62
-            
63
-            <nb-tab tabTitle="Signups"
64
-              [badgeText]="raid.signupcount"
65
-              badgePosition="top right"
66
-              [badgeStatus]="raid.signupcount<40?'warning':'success'">
67
-                <div class="row">
68
-                    <nb-card
69
-                    class="col-12 col-md-6" 
70
-                    *ngIf="raid.tanks.length > 0">
71
-                        <nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
72
-                        <nb-card-body>
73
-                            <div *ngFor="let participant of raid.tanks">
74
-                                <button
75
-                                    (click)="setBench(participant)"
76
-                                    *ngIf="manageRaid" 
77
-                                    nbButton 
78
-                                    outline 
79
-                                    status="warning" 
80
-                                    size="tiny">
81
-                                    B
18
+                        <div *ngIf="canSignup">
19
+                            <div *ngIf="isSignedup">
20
+
21
+                                <p>
22
+                                    You are signed as: {{mySignup.charactername}} ({{mySignup.race}}
23
+                                    {{mySignup.specname}}
24
+                                    {{mySignup.class}})<br />
25
+                                    Status: {{mySignup.status}}
26
+                                </p>
27
+
28
+                                <button (click)="setLate(true)" *ngIf="mySignup.status !== 'Late'" nbButton outline
29
+                                    status="warning" size="medium">
30
+                                    <nb-icon icon="clock-outline"></nb-icon> Late
82
                                 </button>
31
                                 </button>
83
-                                <button
84
-                                    (click)="adminUnsign(participant)"
85
-                                    *ngIf="manageRaid" 
86
-                                    nbButton 
87
-                                    outline 
88
-                                    status="danger" 
89
-                                    size="tiny">
90
-                                    X
32
+                                <button (click)="setLate(false)" *ngIf="mySignup.status === 'Late'" nbButton outline
33
+                                    status="success" size="medium">
34
+                                    <nb-icon icon="checkmark-outline"></nb-icon> On Time
91
                                 </button>
35
                                 </button>
92
-                                <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;" 
93
-                                [routerLink]="'/frontcraft/character/'+participant.charactername">
94
-                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
95
-                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
96
-                                {{ participant.charactername }}
97
-                                </a>
98
-                            </div>
99
-                        </nb-card-body>
100
-                    </nb-card>
101
-
102
-                    <nb-card
103
-                    class="col-12 col-md-6" 
104
-                    *ngIf="raid.tanks.length > 0">
105
-                        <nb-card-header>Healers ({{raid.healers.length}})</nb-card-header>
106
-                        <nb-card-body>
107
-                            <div *ngFor="let participant of raid.healers">
108
-                                <button
109
-                                    (click)="setBench(participant)"
110
-                                    *ngIf="manageRaid" 
111
-                                    nbButton 
112
-                                    outline 
113
-                                    status="warning" 
114
-                                    size="tiny">
115
-                                    B
36
+                                <button (click)="unsign()" nbButton outline status="danger" size="medium">
37
+                                    <nb-icon icon="close"></nb-icon>unsign
116
                                 </button>
38
                                 </button>
117
-                                <button
118
-                                    (click)="adminUnsign(participant)"
119
-                                    *ngIf="manageRaid" 
120
-                                    nbButton 
121
-                                    outline 
122
-                                    status="danger" 
123
-                                    size="tiny">
124
-                                    X
39
+                            </div>
40
+                            <div *ngIf="!isSignedup">
41
+                                <button (click)="signup()" nbButton outline status="success" size="medium">
42
+                                    <nb-icon icon="person-done-outline"></nb-icon> sign up
125
                                 </button>
43
                                 </button>
126
-                                <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;" 
127
-                                [routerLink]="'/frontcraft/character/'+participant.charactername">
128
-                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
129
-                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
130
-                                {{ participant.charactername }}
131
-                                </a>
132
                             </div>
44
                             </div>
133
-                        </nb-card-body>
134
-                    </nb-card>
135
-
136
-                    <ng-container *ngFor="let group of raid.participants | keyvalue">
137
-                        <nb-card
138
-                        class="col-12 col-md-6 col-xl-4" 
139
-                        *ngIf="group.value.length > 0">
140
-                            <nb-card-header>{{group.key}} ({{group.value.length}})</nb-card-header>
141
-                            <nb-card-body>
142
-                                <div *ngFor="let participant of group.value">
143
-                                    <button
144
-                                        (click)="setBench(participant)"
145
-                                        *ngIf="manageRaid" 
146
-                                        nbButton 
147
-                                        outline 
148
-                                        status="warning" 
149
-                                        size="tiny">
150
-                                        B
151
-                                    </button>
152
-                                    <button
153
-                                        (click)="adminUnsign(participant)"
154
-                                        *ngIf="manageRaid" 
155
-                                        nbButton 
156
-                                        outline 
157
-                                        status="danger" 
158
-                                        size="tiny">
159
-                                        X
160
-                                    </button>
161
-                                    <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;" 
162
-                                    [routerLink]="'/frontcraft/character/'+participant.charactername">
163
-                                    <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
164
-                                    <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
165
-                                    {{ participant.charactername }}
166
-                                    </a>
167
-                                </div>
168
-                            </nb-card-body>
169
-                        </nb-card>
170
-                    </ng-container>
171
-                </div>
172
-            </nb-tab>
173
-            <nb-tab tabTitle="Items" *ngIf="isSignedup && isTier">
174
-                <shop [tier]="raid.tier" (onSelect)="itemSelect($event)"></shop>
175
-            </nb-tab>
176
-            <nb-tab tabTitle="Reserves" *ngIf="isTier">
177
-                <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
45
+                        </div>
46
+                    </nb-tab>
47
+                    <nb-tab tabTitle="Signups" [badgeText]="raid.signupcount" badgePosition="top right"
48
+                        [badgeStatus]="raid.signupcount<40?'warning':'success'">
178
 
49
 
179
-                <nb-list>
180
-                    <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
181
-                        <a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}" 
182
-                           target="_blank" 
183
-                           [href]="item.value[0].url">
184
-                           <img style="min-width: 25px; width: 2.25vw; max-width: 50px" 
185
-                           [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.value[0].iconname+'.jpg'" />
186
-                           &nbsp;
187
-                           {{item.key}}
188
-                        </a><br />
189
                         <div class="row">
50
                         <div class="row">
190
-                            <div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
191
-                                [ {{token.level}} ]  
192
-                                <span style="text-transform: capitalize;" [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
193
-                                    {{token.charactername}}
194
-                                </span><br />
195
-                            </div>
51
+                            <nb-card class="col-12 col-md-6" *ngIf="raid.tanks.length > 0">
52
+                                <nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
53
+                                <nb-card-body>
54
+                                    <div *ngFor="let participant of raid.tanks">
55
+                                        <button (click)="setBench(participant)" *ngIf="manageRaid" nbButton outline
56
+                                            status="warning" size="tiny">
57
+                                            B
58
+                                        </button>
59
+                                        <button (click)="adminUnsign(participant)" *ngIf="manageRaid" nbButton outline
60
+                                            status="danger" size="tiny">
61
+                                            X
62
+                                        </button>
63
+                                        <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
64
+                                            [routerLink]="'/frontcraft/character/'+participant.charactername">
65
+                                            <img style="width:20px; height:20px"
66
+                                                [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
67
+                                            <img style="width:20px; height:20px"
68
+                                                [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
69
+                                            {{ participant.charactername }}
70
+                                        </a>
71
+                                    </div>
72
+                                </nb-card-body>
73
+                            </nb-card>
74
+
75
+                            <nb-card class="col-12 col-md-6" *ngIf="raid.tanks.length > 0">
76
+                                <nb-card-header>Healers ({{raid.healers.length}})</nb-card-header>
77
+                                <nb-card-body>
78
+                                    <div *ngFor="let participant of raid.healers">
79
+                                        <button (click)="setBench(participant)" *ngIf="manageRaid" nbButton outline
80
+                                            status="warning" size="tiny">
81
+                                            B
82
+                                        </button>
83
+                                        <button (click)="adminUnsign(participant)" *ngIf="manageRaid" nbButton outline
84
+                                            status="danger" size="tiny">
85
+                                            X
86
+                                        </button>
87
+                                        <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
88
+                                            [routerLink]="'/frontcraft/character/'+participant.charactername">
89
+                                            <img style="width:20px; height:20px"
90
+                                                [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
91
+                                            <img style="width:20px; height:20px"
92
+                                                [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
93
+                                            {{ participant.charactername }}
94
+                                        </a>
95
+                                    </div>
96
+                                </nb-card-body>
97
+                            </nb-card>
98
+
99
+                            <ng-container *ngFor="let group of raid.participants | keyvalue">
100
+                                <nb-card class="col-12 col-md-6 col-xl-4" *ngIf="group.value.length > 0">
101
+                                    <nb-card-header>{{group.key}} ({{group.value.length}})</nb-card-header>
102
+                                    <nb-card-body>
103
+                                        <div *ngFor="let participant of group.value">
104
+                                            <button (click)="setBench(participant)" *ngIf="manageRaid" nbButton outline
105
+                                                status="warning" size="tiny">
106
+                                                B
107
+                                            </button>
108
+                                            <button (click)="adminUnsign(participant)" *ngIf="manageRaid" nbButton
109
+                                                outline status="danger" size="tiny">
110
+                                                X
111
+                                            </button>
112
+                                            <a [ngStyle]="{'color': participant.color}"
113
+                                                style="text-transform: capitalize;"
114
+                                                [routerLink]="'/frontcraft/character/'+participant.charactername">
115
+                                                <img style="width:20px; height:20px"
116
+                                                    [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
117
+                                                <img style="width:20px; height:20px"
118
+                                                    [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
119
+                                                {{ participant.charactername }}
120
+                                            </a>
121
+                                        </div>
122
+                                    </nb-card-body>
123
+                                </nb-card>
124
+                            </ng-container>
196
                         </div>
125
                         </div>
197
-                    </nb-list-item>
198
-                </nb-list>
199
-            </nb-tab>
200
-            <nb-tab tabTitle="Admin" *ngIf="manageRaid">
201
-                <button
202
-                    (click)="startRaid(raid)"
203
-                    nbButton 
204
-                    outline 
205
-                    status="success" 
206
-                    size="medium">
207
-                    start
208
-                </button>
209
-            </nb-tab>
210
-        </nb-tabset>
211
-    </nb-card-body>
212
-</nb-card>
126
+                    </nb-tab>
127
+                    <nb-tab tabTitle="Admin" *ngIf="manageRaid">
128
+                        <button (click)="startRaid(raid)" nbButton outline status="success" size="medium">
129
+                            start
130
+                        </button>
131
+                    </nb-tab>
132
+                </nb-tabset>
133
+            </nb-card-body>
134
+        </nb-card>
135
+    </div>
136
+    <div class="col-12 col-xl-6">
137
+        <nb-card  *ngIf="isTier">
138
+            <nb-card-body>
139
+                <nb-tabset>
140
+                    <nb-tab tabTitle="Reserves">
141
+                        <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search"
142
+                            fullWidth="true">
213
 
143
 
144
+                        <nb-list>
145
+                            <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
146
+                                <a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}"
147
+                                    target="_blank" [href]="item.value[0].url">
148
+                                    <img style="min-width: 25px; width: 2.25vw; max-width: 50px"
149
+                                        [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.value[0].iconname+'.jpg'" />
150
+                                    &nbsp;
151
+                                    {{item.key}}
152
+                                </a><br />
153
+                                <div class="row">
154
+                                    <div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
155
+                                        [ {{token.level}} ]
156
+                                        <span style="text-transform: capitalize;"
157
+                                            [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
158
+                                            {{token.charactername}}
159
+                                        </span><br />
160
+                                    </div>
161
+                                </div>
162
+                            </nb-list-item>
163
+                        </nb-list>
164
+                    </nb-tab>
165
+                    <nb-tab tabTitle="Items" *ngIf="isSignedup">
166
+                        <shop [tier]="raid.tier" (onSelect)="itemSelect($event)"></shop>
167
+                    </nb-tab>
168
+                </nb-tabset>
169
+            </nb-card-body>
170
+        </nb-card>
171
+    </div>
172
+</div>

+ 29
- 11
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts View File

1
-import { Component, OnInit } from '@angular/core';
2
-import { ActivatedRoute, Router } from '@angular/router';
1
+import { Component, OnInit, OnDestroy } from '@angular/core';
2
+import { ActivatedRoute, Router, NavigationStart } from '@angular/router';
3
 import { ApiService as ApiService } from '../../services/login-api';
3
 import { ApiService as ApiService } from '../../services/login-api';
4
 import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
4
 import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
5
 import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
5
 import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
12
   selector: 'raid',
12
   selector: 'raid',
13
   templateUrl: './raid.component.html',
13
   templateUrl: './raid.component.html',
14
 })
14
 })
15
-export class FrontcraftRaidComponent implements OnInit{
15
+export class FrontcraftRaidComponent implements OnInit, OnDestroy{
16
 
16
 
17
     canSignup = false
17
     canSignup = false
18
     isSignedup = false
18
     isSignedup = false
41
     tokens = {}
41
     tokens = {}
42
     displayedtokens = {}
42
     displayedtokens = {}
43
     search = ""
43
     search = ""
44
+    uuid
44
 
45
 
45
     constructor(
46
     constructor(
46
       private api: ApiService,
47
       private api: ApiService,
50
       private toast: NbToastrService
51
       private toast: NbToastrService
51
     ){
52
     ){
52
       window['r'] = this
53
       window['r'] = this
54
+      router.events.subscribe(event => {
55
+        if (event instanceof NavigationStart) {
56
+          this.ngOnDestroy()
57
+        }
58
+      })
59
+    }
60
+
61
+    ngOnDestroy = () => {
62
+      if(this.uuid)
63
+        this.api.get('PubSub').unsubscribe(this.uuid)
53
     }
64
     }
54
 
65
 
55
     async ngOnInit(){
66
     async ngOnInit(){
60
       if(signupFeature){
71
       if(signupFeature){
61
         this.canSignup = true
72
         this.canSignup = true
62
       }
73
       }
63
-      this.refresh()
74
+      await this.refresh()
75
+
76
+      const res = await this.api.get('PubSub').subscribe(""+this.raid.id!, (data: RaidData) => {
77
+        this.display(data)
78
+      })
79
+      this.uuid = res.uuid
64
     }
80
     }
65
 
81
 
82
+ 
83
+
66
     itemSelect = async(item) => {
84
     itemSelect = async(item) => {
67
       this.dialogService.open(FrontcraftBuyTokenComponent, {
85
       this.dialogService.open(FrontcraftBuyTokenComponent, {
68
         context: {
86
         context: {
71
           tier: this.raid.tier,
89
           tier: this.raid.tier,
72
           characterName: this.mySignup.charactername
90
           characterName: this.mySignup.charactername
73
         }
91
         }
74
-      }).onClose.subscribe(() => this.refresh())
92
+      })
75
     }
93
     }
76
 
94
 
77
     signup = async () => {
95
     signup = async () => {
84
         context: {
102
         context: {
85
           raid: this.raid,
103
           raid: this.raid,
86
         } 
104
         } 
87
-      }).onClose.subscribe(()=>{
88
-        this.refresh()
89
-      });
105
+      })
90
     }
106
     }
91
 
107
 
92
     async archiveRaid(raid:Raid){
108
     async archiveRaid(raid:Raid){
110
         id: this.mySignup.characterid, 
126
         id: this.mySignup.characterid, 
111
       }, this.raid)
127
       }, this.raid)
112
       this.toast.show('Success', 'Unsigned', { status: 'success' })
128
       this.toast.show('Success', 'Unsigned', { status: 'success' })
113
-      this.refresh()
114
     }
129
     }
115
 
130
 
116
     setLate = async (value:boolean) => {
131
     setLate = async (value:boolean) => {
123
         id: this.mySignup.characterid,
138
         id: this.mySignup.characterid,
124
       }, this.raid, value)
139
       }, this.raid, value)
125
       this.toast.show('Signup', 'Success', { status: 'success' })
140
       this.toast.show('Signup', 'Success', { status: 'success' })
126
-      this.refresh()
127
     }
141
     }
128
 
142
 
129
     adminUnsign = async() => {
143
     adminUnsign = async() => {
133
         ...this.mySignup,
147
         ...this.mySignup,
134
         id: this.mySignup.characterid, 
148
         id: this.mySignup.characterid, 
135
       }, this.raid)
149
       }, this.raid)
136
-      this.refresh()
137
     }
150
     }
138
 
151
 
139
     refresh = async () => {
152
     refresh = async () => {
143
       const raiddata = await raidManager.getRaidData(<any>{
156
       const raiddata = await raidManager.getRaidData(<any>{
144
         id: param
157
         id: param
145
       })
158
       })
159
+      this.display(raiddata)
160
+      
161
+    }
162
+
163
+    display =  async (raiddata:RaidData)  => {
146
       this.isTier = allItems[raiddata.tier] != null
164
       this.isTier = allItems[raiddata.tier] != null
147
 
165
 
148
       this.raid = raiddata
166
       this.raid = raiddata

+ 24
- 17
src/frontend/src/app/frontcraft/pages/raids/raids.component.html View File

16
     class="raidlist"
16
     class="raidlist"
17
     style="cursor: pointer;">
17
     style="cursor: pointer;">
18
       <div class="row">
18
       <div class="row">
19
-        <div class="col-2">
20
-          <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" style="height: 75px" />
21
-        </div>
22
-
23
-        <div class="col-2 vcenter">
24
-          {{raid.title}}
25
-         </div>
26
-        
27
-        <div class="col-2 vcenter">
28
-          <nb-icon icon="checkmark-circle"></nb-icon> {{raid.signupcount}} / {{raid.size}}<br>
29
-        </div>
30
-
31
-        <div class="col-2 vcenter">
32
-          <nb-icon icon="clock-outline"></nb-icon> {{raid.start | date : 'HH:mm'}}
33
-        </div>
19
+        <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" 
20
+        style="object-fit: contain"
21
+        class="col-1 col-s-3" />
34
 
22
 
35
-        <div class="col-4 vcenter">
36
-          <nb-icon icon="calendar-outline"></nb-icon> {{raid.start | date : 'EEEE MMMM d'}}
23
+        <div class="col-11 col-s-9" >
24
+          <div class="row">
25
+            <div class="col-12" style="padding-top: 5px">
26
+              <h4>
27
+                {{raid.title}}
28
+              </h4>
29
+            </div>
30
+          </div>
31
+          <div class="row" style="padding-top: 5px; padding-bottom: 5px; color:darkgray">
32
+            <div class="col-6 col-md-3">
33
+              <nb-icon icon="checkmark-circle"></nb-icon> {{raid.signupcount}} / {{raid.size}}<br>
34
+            </div>
35
+    
36
+            <div class="col-6 col-md-3">
37
+              <nb-icon icon="clock-outline"></nb-icon> {{raid.start | date : 'HH:mm'}}
38
+            </div>
39
+    
40
+            <div class="col-12 col-md-6">
41
+              <nb-icon icon="calendar-outline"></nb-icon> {{raid.start | date : 'EEE MMM d'}}
42
+            </div>
43
+          </div>
37
         </div>
44
         </div>
38
       </div>
45
       </div>
39
     </nb-list-item>
46
     </nb-list-item>

+ 10
- 3
src/frontend/src/app/frontcraft/pages/raids/raids.component.scss View File

10
   background-color: #293259;
10
   background-color: #293259;
11
 }
11
 }
12
 
12
 
13
-.vcenter {
14
-  height: 75px;
15
-  padding-top: 30px;
13
+.raid {
14
+  height: 75px
15
+}
16
+
17
+.row {
18
+  margin: -0.5rem;
19
+}
20
+
21
+h4 {
22
+  font-weight: normal
16
 }
23
 }

+ 22
- 6
src/frontend/src/app/frontcraft/pages/raids/raids.component.ts View File

1
-import { Component, OnInit } from '@angular/core';
1
+import { Component, OnInit, OnDestroy } from '@angular/core';
2
 import { ApiService } from '../../services/login-api';
2
 import { ApiService } from '../../services/login-api';
3
 import { NbWindowService, NbDialogService } from '@nebular/theme';
3
 import { NbWindowService, NbDialogService } from '@nebular/theme';
4
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
4
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
5
+import { Router, NavigationStart } from '@angular/router';
5
 
6
 
6
 @Component({
7
 @Component({
7
   selector: 'raids',
8
   selector: 'raids',
8
   templateUrl: 'raids.component.html',
9
   templateUrl: 'raids.component.html',
9
   styleUrls: ['raids.component.scss'],
10
   styleUrls: ['raids.component.scss'],
10
 })
11
 })
11
-export class FrontcraftRaidsComponent implements OnInit{
12
+export class FrontcraftRaidsComponent implements OnInit, OnDestroy{
12
 
13
 
13
 
14
 
14
   manageRaid
15
   manageRaid
15
   raids = []
16
   raids = []
16
   oldraids = []
17
   oldraids = []
17
   pageSize = 10;
18
   pageSize = 10;
19
+  uuid
18
 
20
 
19
   constructor(
21
   constructor(
20
     private api: ApiService,
22
     private api: ApiService,
23
+    private router: Router,
21
     private dialogService: NbDialogService
24
     private dialogService: NbDialogService
22
   ) {
25
   ) {
23
     this.manageRaid = this.api.get('manageRaid')
26
     this.manageRaid = this.api.get('manageRaid')
27
+    router.events.subscribe(event => {
28
+      if (event instanceof NavigationStart) {
29
+        this.ngOnDestroy()
30
+      }
31
+    })
32
+  }
24
 
33
 
34
+  ngOnDestroy = () => {
35
+    console.log("boom");
36
+
37
+    if(this.uuid)
38
+      this.api.get('PubSub').unsubscribe(this.uuid)
25
   }
39
   }
26
 
40
 
27
-  ngOnInit(): void {
41
+  async ngOnInit() {
42
+    const res = await this.api.get('PubSub').subscribe("raids", () => {
43
+      this.refresh()
44
+    })
45
+    this.uuid = res.uuid
28
     this.refresh()
46
     this.refresh()
29
   }
47
   }
30
 
48
 
46
       context: {
64
       context: {
47
         templates: this.oldraids
65
         templates: this.oldraids
48
       } 
66
       } 
49
-    }).onClose.subscribe(()=>{
50
-      this.refresh()
51
-    });
67
+    })
52
 
68
 
53
   }
69
   }
54
 }
70
 }

+ 58
- 7
src/frontend/src/app/frontcraft/pages/rules/rules.component.html View File

2
     <nb-card-body>
2
     <nb-card-body>
3
         <nb-tabset>
3
         <nb-tabset>
4
             <nb-tab tabTitle="Info">
4
             <nb-tab tabTitle="Info">
5
-                Smart text here
5
+                <h3>How it works</h3>
6
+                <ul>
7
+                    <li>
8
+                        Everyone starts out with 1 soft reserve right per raid tier (you can see them in your user profile)
9
+                    </li>
10
+                    <li>
11
+                        The tiers are: MC+Ony, BWL, ZG, AQ20, AQ40, Naxx
12
+                    </li>
13
+                    <li>
14
+                        You gain 1 reserve right for a raid you attend. 2 if you were benched. Rights are granted on raid start.
15
+                    </li>
16
+                    <li>
17
+                        When you sign up to a raid you can spend your reserve rights
18
+                    </li>
19
+                    <li>
20
+                        Every week you can re-reserve the same item to build a streak on it
21
+                    </li>
22
+                    <!--
23
+                    <li>
24
+                        Steaks are color coded. If this means anything will be decided by guild culture: 
25
+                        <span style="color: #ff8000">[+ 10]</span>
26
+                        <span style="color: #a335ee">[9. 8]</span>
27
+                        <span style="color: #0070dd">[7, 6]</span>
28
+                        <span style="color: #1eff00">[5, 4]</span>
29
+                        <span style="color: #ffffff">[3, 2]</span>
30
+                        <span style="color: #9d9d9d">[1]</span>
31
+                    </li>
32
+                    -->
33
+                </ul>
34
+                <br />
35
+                <h3>Specifics about streaks</h3>
36
+                <ul>
37
+                    <li>
38
+                        Some classes and races get an initial boost to specific reserves. The list is on the second tab. 
39
+                    </li>
40
+                    <li>
41
+                        Switching the selected item destroys previous streaks. (Streaks must be continued without switchup)    
42
+                    </li>
43
+                    <li>
44
+                        If you have more than 1 softreserve you can reserve multiple different items. You may only continue one streak the following raid.
45
+                    </li>
46
+                    <li>
47
+                        If you have more than 1 softreserve you can reserve the same item several times to increase its streak.
48
+                    </li>
49
+                    <li>
50
+                        The softreserve counter, Reserves, and Streaks are tiers-specific and only count within their tier.
51
+                    </li>
52
+                    <li>
53
+                        Canceling the signup refunds active reserves and continued streaks. Destroyed streaks cannot be recovered. 
54
+                    </li>
55
+                </ul>
6
             </nb-tab>
56
             </nb-tab>
7
             <nb-tab tabTitle="priorities">
57
             <nb-tab tabTitle="priorities">
8
                 <nb-list>
58
                 <nb-list>
9
                     <nb-list-item *ngFor="let item of rules | keyvalue">
59
                     <nb-list-item *ngFor="let item of rules | keyvalue">
10
                         <wowhead [item]="item.value[0]"></wowhead><br>
60
                         <wowhead [item]="item.value[0]"></wowhead><br>
11
-                        <span *ngFor="let rule of item.value" [nbPopover]="templateRef" nbPopoverTrigger="hover">
12
-                            <ng-template #templateRef>
13
-                                <span style="color:white">{{rule.description}}</span>
14
-                            </ng-template>
15
-                            <span *ngIf="rule.modifier>0">+</span>{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span> <br />
16
-                        </span>
61
+                        <div class="row" *ngFor="let rule of item.value">
62
+                            <div class="col-4">
63
+                                <span *ngIf="rule.modifier>0">+</span>{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span> 
64
+                            </div>
65
+                            <div class="col-8" style="color:white"> ({{rule.description}})</div>
66
+                            <br />
67
+                        </div>
17
                     </nb-list-item>
68
                     </nb-list-item>
18
                 </nb-list>
69
                 </nb-list>
19
             </nb-tab>
70
             </nb-tab>

+ 312
- 251
test/backendTest.ts View File

1
 import { Injector } from "../src/backend/Injector/Injector";
1
 import { Injector } from "../src/backend/Injector/Injector";
2
 import { FrontworkAdmin } from "../src/backend/Admin/Admin";
2
 import { FrontworkAdmin } from "../src/backend/Admin/Admin";
3
-import { T1 } from "../src/backend/Types/Items";
3
+import { T1, T2, Tiers } from "../src/backend/Types/Items";
4
 
4
 
5
 import { RPCSocket } from "rpclibrary";
5
 import { RPCSocket } from "rpclibrary";
6
 import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, SRPriority, Spec, Signup } from "../src/backend/Types/Types";
6
 import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, SRPriority, Spec, Signup } from "../src/backend/Types/Types";
8
 
8
 
9
 
9
 
10
 type protoAccount<C extends Class = Class> = {
10
 type protoAccount<C extends Class = Class> = {
11
-    name : string,
11
+    name: string,
12
     pwHash?: string
12
     pwHash?: string
13
-    rank : Rank,
13
+    rank: Rank,
14
     race: Race,
14
     race: Race,
15
     class: C,
15
     class: C,
16
     spec: SpecT[C]
16
     spec: SpecT[C]
39
 }
39
 }
40
 
40
 
41
 const defaultPermissions = [
41
 const defaultPermissions = [
42
-{   rpcname: 'signup', ...trialsAndUp
43
-},{ rpcname: 'reset', ...adminsOnly 
44
-},{ rpcname: 'modifyPermissions', ...adminsOnly 
45
-},{ rpcname: 'manageGuild', ...adminsOnly
46
-},{ rpcname: 'managePriorities', ...adminsOnly
47
-},{ rpcname: 'softreserveCurrency', ...adminsOnly
48
-},{ rpcname: 'manageRaid', ...adminsOnly
49
-}]
50
-
51
-const testAccounts : protoAccount[] = [
42
+    {
43
+        rpcname: 'signup', ...trialsAndUp
44
+    }, {
45
+        rpcname: 'reset', ...adminsOnly
46
+    }, {
47
+        rpcname: 'modifyPermissions', ...adminsOnly
48
+    }, {
49
+        rpcname: 'manageGuild', ...adminsOnly
50
+    }, {
51
+        rpcname: 'managePriorities', ...adminsOnly
52
+    }, {
53
+        rpcname: 'softreserveCurrency', ...adminsOnly
54
+    }, {
55
+        rpcname: 'manageRaid', ...adminsOnly
56
+    }]
57
+
58
+const testAccounts: protoAccount[] = [
52
     {
59
     {
53
         name: 'Rain',
60
         name: 'Rain',
54
         race: 'Human',
61
         race: 'Human',
55
         class: 'Warrior',
62
         class: 'Warrior',
56
         spec: 'Protection',
63
         spec: 'Protection',
57
         rank: 'Guildmaster'
64
         rank: 'Guildmaster'
58
-    },{
65
+    }, {
59
         name: 'Celinda',
66
         name: 'Celinda',
60
         class: 'Warrior',
67
         class: 'Warrior',
61
         race: 'Night Elf',
68
         race: 'Night Elf',
62
         spec: 'Protection',
69
         spec: 'Protection',
63
         rank: 'Officer'
70
         rank: 'Officer'
64
-    },{
71
+    }, {
65
         name: 'Silver',
72
         name: 'Silver',
66
         class: 'Druid',
73
         class: 'Druid',
67
         race: 'Night Elf',
74
         race: 'Night Elf',
68
         spec: 'Restoration',
75
         spec: 'Restoration',
69
         rank: 'Raider'
76
         rank: 'Raider'
70
-    },{
77
+    }, {
71
         name: 'Dagger',
78
         name: 'Dagger',
72
         race: 'Dwarf',
79
         race: 'Dwarf',
73
         class: 'Rogue',
80
         class: 'Rogue',
74
         spec: 'Assassination',
81
         spec: 'Assassination',
75
         rank: 'Classleader'
82
         rank: 'Classleader'
76
-    },{
83
+    }, {
77
         name: 'Hope',
84
         name: 'Hope',
78
         class: 'Paladin',
85
         class: 'Paladin',
79
         race: 'Human',
86
         race: 'Human',
80
         spec: 'Holy',
87
         spec: 'Holy',
81
         rank: 'Classleader'
88
         rank: 'Classleader'
82
-    },{
89
+    }, {
83
         name: 'Shrekd',
90
         name: 'Shrekd',
84
         class: 'Warrior',
91
         class: 'Warrior',
85
         race: 'Dwarf',
92
         race: 'Dwarf',
86
         spec: 'Fury',
93
         spec: 'Fury',
87
         rank: 'Classleader'
94
         rank: 'Classleader'
88
-    },{
95
+    }, {
89
         name: 'Teeniweeni',
96
         name: 'Teeniweeni',
90
         class: 'Warlock',
97
         class: 'Warlock',
91
         race: 'Gnome',
98
         race: 'Gnome',
92
         spec: 'Demonology',
99
         spec: 'Demonology',
93
         rank: 'Classleader'
100
         rank: 'Classleader'
94
-    },{
101
+    }, {
95
         name: 'Hagibaba',
102
         name: 'Hagibaba',
96
         class: 'Priest',
103
         class: 'Priest',
97
         race: 'Human',
104
         race: 'Human',
98
         spec: 'Discipline',
105
         spec: 'Discipline',
99
         rank: 'Classleader'
106
         rank: 'Classleader'
100
-    },{
107
+    }, {
101
         name: 'Muffinbreak',
108
         name: 'Muffinbreak',
102
         class: 'Mage',
109
         class: 'Mage',
103
         race: 'Gnome',
110
         race: 'Gnome',
109
 
116
 
110
 describe('Frontcraft', () => {
117
 describe('Frontcraft', () => {
111
     let auth: Auth,
118
     let auth: Auth,
112
-        adminUser : User,
119
+        adminUser: User,
113
         server: FrontworkAdmin,
120
         server: FrontworkAdmin,
114
-        client : RPCSocket & FrontcraftIfc,
115
-        adminClient : RPCSocket & FrontcraftFeatureIfc,
121
+        client: RPCSocket & FrontcraftIfc,
122
+        adminClient: RPCSocket & FrontcraftFeatureIfc,
116
         raids: Raid[] = [],
123
         raids: Raid[] = [],
117
-        users : {[username in string] : { account: User, character: Character, auth: Auth, signup?:Signup, item?:string }} = {}
124
+        users: { [username in string]: { account: User, character: Character, auth: Auth, signup?: Signup, item?: string } } = {}
118
 
125
 
119
     const createAccount = (user: User) => {
126
     const createAccount = (user: User) => {
120
         return client.UserManager.createUser(user)
127
         return client.UserManager.createUser(user)
121
     }
128
     }
122
 
129
 
123
-    const createAccountAndUser = async (acc : protoAccount) => {
130
+    const createAccountAndUser = async (acc: protoAccount) => {
124
         const account = await createAccount({
131
         const account = await createAccount({
125
             pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
132
             pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
126
             rank: acc.rank,
133
             rank: acc.rank,
141
         }
148
         }
142
     }
149
     }
143
 
150
 
144
-    before(function (done){
145
-        this.timeout(10000); 
151
+    before(function (done) {
152
+        this.timeout(10000);
146
 
153
 
147
         server = Injector.resolve<FrontworkAdmin>(FrontworkAdmin)
154
         server = Injector.resolve<FrontworkAdmin>(FrontworkAdmin)
148
         server.start().then((_server) => {
155
         server.start().then((_server) => {
149
-            
156
+
150
             RPCSocket.makeSocket<FrontcraftIfc>(20000, 'localhost').then(_client => {
157
             RPCSocket.makeSocket<FrontcraftIfc>(20000, 'localhost').then(_client => {
151
                 client = _client
158
                 client = _client
152
-                
159
+
153
 
160
 
154
                 createAccount({
161
                 createAccount({
155
                     pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //hash("a")
162
                     pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //hash("a")
160
 
167
 
161
                     client.UserManager.login(adminUser.username, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb').then(auth => {
168
                     client.UserManager.login(adminUser.username, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb').then(auth => {
162
                         const sock = new RPCSocket(
169
                         const sock = new RPCSocket(
163
-                            auth.port, 
170
+                            auth.port,
164
                             "localhost"
171
                             "localhost"
165
                         )
172
                         )
166
 
173
 
170
                                 console.log("I got kicked");
177
                                 console.log("I got kicked");
171
                             })
178
                             })
172
                             sock.hook('getUserData', () => auth)
179
                             sock.hook('getUserData', () => auth)
173
-                            sock.hook('navigate', (where:string) => {
174
-                                console.log("Nagivate client to "+where);
180
+                            sock.hook('navigate', (where: string) => {
181
+                                console.log("Nagivate client to " + where);
175
                             })
182
                             })
176
                             sock.on('error', (e) => {
183
                             sock.on('error', (e) => {
177
-                                console.log('Socket error',  e)
184
+                                console.log('Socket error', e)
178
                             })
185
                             })
179
                             done()
186
                             done()
180
                         })
187
                         })
184
         }).catch(done)
191
         }).catch(done)
185
     })
192
     })
186
 
193
 
187
-    after(()=>{
194
+    after(() => {
188
         client.destroy()
195
         client.destroy()
189
         adminClient.destroy()
196
         adminClient.destroy()
190
         server.stop()
197
         server.stop()
193
     it('create raids', (done) => {
200
     it('create raids', (done) => {
194
         let insertRaid = <Raid>{
201
         let insertRaid = <Raid>{
195
             description: "Test raid 1",
202
             description: "Test raid 1",
196
-            title: 'MC',
203
+            title: 'BWL :D',
197
             start: Date.now().toString(),
204
             start: Date.now().toString(),
198
-            tier: 'MC'
205
+            tier: 'BWL'
199
         }
206
         }
200
 
207
 
201
         adminClient.manageRaid.createRaid(insertRaid).then(() => {
208
         adminClient.manageRaid.createRaid(insertRaid).then(() => {
202
-            client.RaidManager.getRaids().then((r)=>{
203
-                if(r[0].title === insertRaid.title 
204
-                && r[0].description === insertRaid.description
205
-                && r[0].tier === "MC"){
209
+            client.RaidManager.getRaids().then((r) => {
210
+                if (r[0].title === insertRaid.title
211
+                    && r[0].description === insertRaid.description
212
+                    && r[0].tier === "BWL") {
206
                     raids.push(r[0])
213
                     raids.push(r[0])
207
                     done()
214
                     done()
208
                 }
215
                 }
210
         }).catch(done)
217
         }).catch(done)
211
     })
218
     })
212
 
219
 
213
-    it('create users', (done)=>{
220
+    it('create users', (done) => {
214
         Promise.all(testAccounts.map(acc => createAccountAndUser(acc))).then(accs => {
221
         Promise.all(testAccounts.map(acc => createAccountAndUser(acc))).then(accs => {
215
-            if(accs.length === testAccounts.length){
222
+            if (accs.length === testAccounts.length) {
216
                 accs.forEach(acc => {
223
                 accs.forEach(acc => {
217
                     users[acc.account.username] = acc
224
                     users[acc.account.username] = acc
218
                 })
225
                 })
221
         }).catch(done)
228
         }).catch(done)
222
     })
229
     })
223
 
230
 
224
-    it('should sign up', (done)=>{
231
+    it('should sign up', (done) => {
225
         Promise.all(Object.values(users).map((user) =>
232
         Promise.all(Object.values(users).map((user) =>
226
             adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false).catch(done)
233
             adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false).catch(done)
227
         )).then(x => {
234
         )).then(x => {
228
             adminClient.signup.getSignups(raids[0]).then(s => {
235
             adminClient.signup.getSignups(raids[0]).then(s => {
229
-                if(s.length == testAccounts.length){
236
+                if (s.length == testAccounts.length) {
230
                     s.forEach(sign => {
237
                     s.forEach(sign => {
231
                         users[sign.username].signup = sign
238
                         users[sign.username].signup = sign
232
                     })
239
                     })
233
                     done()
240
                     done()
234
-                }else{
235
-                    done("Unexpected number of signups: "+s.length)
241
+                } else {
242
+                    done("Unexpected number of signups: " + s.length)
236
                 }
243
                 }
237
             })
244
             })
238
         })
245
         })
239
     })
246
     })
240
 
247
 
241
-    it('calculate priorities', (done)=>{
242
-        const makePrio = async (itemname:string, spec?: Spec, race?:Race, mod:number = 0, description:string = "") => {
248
+    it('calculate priorities', (done) => {
249
+        const makePrio = async (itemname: string, spec?: Spec, race?: Race, mod: number = 0, description: string = "") => {
243
             let specid
250
             let specid
244
-            if(spec)
251
+            if (spec)
245
                 specid = await client.CharacterManager.getSpecId(spec.class, <any>spec.specname)
252
                 specid = await client.CharacterManager.getSpecId(spec.class, <any>spec.specname)
246
-            
253
+
247
             await adminClient.managePriorities.setPriority(itemname, {
254
             await adminClient.managePriorities.setPriority(itemname, {
248
                 specid: specid,
255
                 specid: specid,
249
                 race: race,
256
                 race: race,
252
             })
259
             })
253
         }
260
         }
254
 
261
 
255
-              
262
+
256
         Promise.all([
263
         Promise.all([
257
             makePrio(
264
             makePrio(
258
-                'Bracers of Arcane Accuracy', 
259
-                {class:'Warlock', specname:'Demonology'}, 
265
+                'Bracers of Arcane Accuracy',
266
+                { class: 'Warlock', specname: 'Demonology' },
260
                 undefined, 2, "hit bias"
267
                 undefined, 2, "hit bias"
261
             ),
268
             ),
262
             makePrio(
269
             makePrio(
263
-                'Bracers of Arcane Accuracy', 
264
-                {class:'Warlock', specname:'Affliction'}, 
270
+                'Bracers of Arcane Accuracy',
271
+                { class: 'Warlock', specname: 'Affliction' },
265
                 undefined, 2, "hit bias"
272
                 undefined, 2, "hit bias"
266
             ),
273
             ),
267
             makePrio(
274
             makePrio(
268
-                'Bracers of Arcane Accuracy', 
269
-                {class:'Warlock', specname:'Destruction'}, 
275
+                'Bracers of Arcane Accuracy',
276
+                { class: 'Warlock', specname: 'Destruction' },
270
                 undefined, 2, "hit bias"
277
                 undefined, 2, "hit bias"
271
             ),
278
             ),
272
             makePrio(
279
             makePrio(
273
-                'Bracers of Arcane Accuracy', 
274
-                {class:'Mage', specname:'Arcane'}, 
280
+                'Bracers of Arcane Accuracy',
281
+                { class: 'Mage', specname: 'Arcane' },
275
                 undefined, 1, "hit bias"
282
                 undefined, 1, "hit bias"
276
             ),
283
             ),
277
             makePrio(
284
             makePrio(
278
-                'Bracers of Arcane Accuracy', 
279
-                {class:'Mage', specname:'Frost'}, 
285
+                'Bracers of Arcane Accuracy',
286
+                { class: 'Mage', specname: 'Frost' },
280
                 undefined, 1, "hit bias"
287
                 undefined, 1, "hit bias"
281
             ),
288
             ),
282
             makePrio(
289
             makePrio(
283
-                'Bracers of Arcane Accuracy', 
284
-                {class:'Mage', specname:'Fire'}, 
290
+                'Bracers of Arcane Accuracy',
291
+                { class: 'Mage', specname: 'Fire' },
285
                 undefined, 1, "hit bias"
292
                 undefined, 1, "hit bias"
286
             ),
293
             ),
287
 
294
 
288
             makePrio(
295
             makePrio(
289
-                'Maladath, Runed Blade of the Black Flight', 
296
+                'Maladath, Runed Blade of the Black Flight',
290
                 undefined,
297
                 undefined,
291
-                "Human", -2, "(1) Non-Human"
292
-            ),
293
-            makePrio(
294
-                'Maladath, Runed Blade of the Black Flight', 
295
-                {class:'Rogue', specname:'Subtlety'}, 
296
-                undefined, 2, "...Rogues (weapon skill bias)"
298
+                "Human", -2, "[1] Non-Human"
297
             ),
299
             ),
298
             makePrio(
300
             makePrio(
299
-                'Maladath, Runed Blade of the Black Flight', 
300
-                {class:'Rogue', specname:'Combat'}, 
301
-                undefined, 2, "...Rogues (weapon skill bias)"
301
+                'Maladath, Runed Blade of the Black Flight',
302
+                { class: 'Rogue', specname: 'Combat' },
303
+                undefined, 2, "Weapon skill bias"
302
             ),
304
             ),
303
             makePrio(
305
             makePrio(
304
-                'Maladath, Runed Blade of the Black Flight', 
305
-                {class:'Rogue', specname:'Assassination'}, 
306
-                undefined, 2, "...Rogues (weapon skill bias)"
306
+                'Maladath, Runed Blade of the Black Flight',
307
+                { class: 'Warrior', specname: 'Fury' },
308
+                'Human', 4, "+2 Fury Warrior (weapon skill bias), +2 to offset [1]"
307
             ),
309
             ),
308
             makePrio(
310
             makePrio(
309
-                'Maladath, Runed Blade of the Black Flight', 
310
-                {class:'Warrior', specname:'Fury'}, 
311
-                'Human', 4, "+2 Fury Warrior (weapon skill bias), +2 to offset (1)"
311
+                'Maladath, Runed Blade of the Black Flight',
312
+                { class: 'Warrior', specname: 'Protection' },
313
+                'Human', 5, "+3 Prot Warrior, +2 to offset [1]"
312
             ),
314
             ),
313
 
315
 
314
             makePrio(
316
             makePrio(
315
-                'Cloak of Firemaw', 
316
-                {class:'Rogue', specname:'Assassination'}, 
317
+                'Cloak of Firemaw',
318
+                { class: 'Rogue', specname: 'Assassination' },
317
                 undefined, 2, "agi-to-ap bias"
319
                 undefined, 2, "agi-to-ap bias"
318
             ),
320
             ),
319
             makePrio(
321
             makePrio(
320
-                'Cloak of Firemaw', 
321
-                {class:'Rogue', specname:'Combat'}, 
322
+                'Cloak of Firemaw',
323
+                { class: 'Rogue', specname: 'Combat' },
322
                 undefined, 2, "agi-to-ap bias"
324
                 undefined, 2, "agi-to-ap bias"
323
             ),
325
             ),
324
             makePrio(
326
             makePrio(
325
-                'Cloak of Firemaw', 
326
-                {class:'Rogue', specname:'Subtlety'}, 
327
+                'Cloak of Firemaw',
328
+                { class: 'Rogue', specname: 'Subtlety' },
327
                 undefined, 2, "agi-to-ap bias"
329
                 undefined, 2, "agi-to-ap bias"
328
             ),
330
             ),
329
 
331
 
330
             makePrio(
332
             makePrio(
331
-                'Band of Forced Concentration', 
332
-                {class:'Warlock', specname:'Demonology'}, 
333
+                'Band of Forced Concentration',
334
+                { class: 'Warlock', specname: 'Demonology' },
333
                 undefined, 2, "hit bias"
335
                 undefined, 2, "hit bias"
334
             ),
336
             ),
335
             makePrio(
337
             makePrio(
336
-                'Band of Forced Concentration', 
337
-                {class:'Warlock', specname:'Affliction'}, 
338
+                'Band of Forced Concentration',
339
+                { class: 'Warlock', specname: 'Affliction' },
338
                 undefined, 2, "hit bias"
340
                 undefined, 2, "hit bias"
339
             ),
341
             ),
340
             makePrio(
342
             makePrio(
341
-                'Band of Forced Concentration', 
342
-                {class:'Warlock', specname:'Destruction'}, 
343
+                'Band of Forced Concentration',
344
+                { class: 'Warlock', specname: 'Destruction' },
343
                 undefined, 2, "hit bias"
345
                 undefined, 2, "hit bias"
344
             ),
346
             ),
345
             makePrio(
347
             makePrio(
346
-                'Band of Forced Concentration', 
347
-                {class:'Mage', specname:'Arcane'}, 
348
+                'Band of Forced Concentration',
349
+                { class: 'Mage', specname: 'Arcane' },
348
                 undefined, 1, "hit bias"
350
                 undefined, 1, "hit bias"
349
             ),
351
             ),
350
             makePrio(
352
             makePrio(
351
-                'Band of Forced Concentration', 
352
-                {class:'Mage', specname:'Frost'}, 
353
+                'Band of Forced Concentration',
354
+                { class: 'Mage', specname: 'Frost' },
353
                 undefined, 1, "hit bias"
355
                 undefined, 1, "hit bias"
354
             ),
356
             ),
355
             makePrio(
357
             makePrio(
356
-                'Band of Forced Concentration', 
357
-                {class:'Mage', specname:'Fire'}, 
358
+                'Band of Forced Concentration',
359
+                { class: 'Mage', specname: 'Fire' },
358
                 undefined, 1, "hit bias"
360
                 undefined, 1, "hit bias"
359
             ),
361
             ),
360
 
362
 
361
             makePrio(
363
             makePrio(
362
-                'Drake Fang Talisman', 
363
-                {class:'Rogue', specname:'Assassination'}, 
364
+                'Chromatic Boots',
365
+                { class: 'Warrior', specname: 'Protection' },
366
+                undefined, 2, "hit bias"
367
+            ),
368
+
369
+            makePrio(
370
+                'Crul\'shorukh, Edge of Chaos',
371
+                undefined,
372
+                "Human", -2, "Non-human"
373
+            ),
374
+            makePrio(
375
+                'Crul\'shorukh, Edge of Chaos',
376
+                { class: 'Warrior', specname: 'Protection' },
377
+                undefined, 2, "nice dps bias"
378
+            ),
379
+            makePrio(
380
+                'Crul\'shorukh, Edge of Chaos',
381
+                { class: 'Warrior', specname: 'Fury' },
382
+                undefined, 2, "nice dps bias"
383
+            ),
384
+
385
+            makePrio(
386
+                'Drake Talon Pauldrons',
387
+                { class: 'Warrior', specname:'Protection'},
388
+                undefined, 2, 'dodge + stats-to-threat bias'
389
+            ),
390
+            
391
+            makePrio(
392
+                'Helm of Endless Rage',
393
+                { class: 'Warrior', specname:'Protection'},
394
+                undefined, 2, 'stats-to-threat bias'
395
+            ),
396
+
397
+            makePrio(
398
+                'Drake Fang Talisman',
399
+                { class: 'Warrior', specname: 'Protection' },
400
+                undefined, 5, "hit bias"
401
+            ),
402
+            makePrio(
403
+                'Drake Fang Talisman',
404
+                { class: 'Rogue', specname: 'Assassination' },
364
                 undefined, 4, "hit bias"
405
                 undefined, 4, "hit bias"
365
             ),
406
             ),
366
             makePrio(
407
             makePrio(
367
-                'Drake Fang Talisman', 
368
-                {class:'Rogue', specname:'Combat'}, 
408
+                'Drake Fang Talisman',
409
+                { class: 'Rogue', specname: 'Combat' },
369
                 undefined, 4, "hit bias"
410
                 undefined, 4, "hit bias"
370
             ),
411
             ),
371
             makePrio(
412
             makePrio(
372
-                'Drake Fang Talisman', 
373
-                {class:'Rogue', specname:'Subtlety'}, 
413
+                'Drake Fang Talisman',
414
+                { class: 'Rogue', specname: 'Subtlety' },
374
                 undefined, 4, "hit bias"
415
                 undefined, 4, "hit bias"
375
             ),
416
             ),
376
             makePrio(
417
             makePrio(
377
-                'Drake Fang Talisman', 
378
-                {class:'Warrior', specname:'Fury'}, 
418
+                'Drake Fang Talisman',
419
+                { class: 'Warrior', specname: 'Fury' },
379
                 undefined, 2, "hit bias"
420
                 undefined, 2, "hit bias"
380
             ),
421
             ),
381
             makePrio(
422
             makePrio(
382
-                'Drake Fang Talisman', 
383
-                {class:'Druid', specname:'Feral (DPS)'}, 
423
+                'Drake Fang Talisman',
424
+                { class: 'Druid', specname: 'Feral (DPS)' },
384
                 undefined, 2, "hit bias"
425
                 undefined, 2, "hit bias"
385
             ),
426
             ),
386
 
427
 
387
             makePrio(
428
             makePrio(
388
-                'Circle of Applied Force', 
389
-                {class:'Warrior', specname:'Fury'}, 
429
+                'Circle of Applied Force',
430
+                { class: 'Warrior', specname: 'Fury' },
390
                 undefined, 2, "str-to-ap bias"
431
                 undefined, 2, "str-to-ap bias"
391
             ),
432
             ),
392
             makePrio(
433
             makePrio(
393
-                'Circle of Applied Force', 
394
-                {class:'Druid', specname:'Feral (DPS)'}, 
395
-                undefined, 2, "str-to-ap bias"
434
+                'Circle of Applied Force',
435
+                { class: 'Druid', specname: 'Feral (DPS)' },
436
+                undefined, 3, "str-to-ap bias + agi-to-ap bias"
396
             ),
437
             ),
397
 
438
 
398
             makePrio(
439
             makePrio(
399
-                'Empowered Leggings', 
400
-                {class:'Paladin', specname:'Holy'}, 
440
+                'Empowered Leggings',
441
+                { class: 'Paladin', specname: 'Holy' },
401
                 undefined, 2, "crit bias"
442
                 undefined, 2, "crit bias"
402
             ),
443
             ),
403
             makePrio(
444
             makePrio(
404
-                'Empowered Leggings', 
405
-                {class:'Druid', specname:'Restoration'}, 
445
+                'Empowered Leggings',
446
+                { class: 'Druid', specname: 'Restoration' },
406
                 undefined, 2, "crit bias"
447
                 undefined, 2, "crit bias"
407
             ),
448
             ),
408
 
449
 
409
             makePrio(
450
             makePrio(
410
-                'Boots of the Shadow Flame', 
411
-                {class:'Rogue', specname:'Assassination'}, 
451
+                'Boots of the Shadow Flame',
452
+                { class: 'Rogue', specname: 'Assassination' },
412
                 undefined, 2, "hit bias"
453
                 undefined, 2, "hit bias"
413
             ),
454
             ),
414
             makePrio(
455
             makePrio(
415
-                'Boots of the Shadow Flame', 
416
-                {class:'Rogue', specname:'Combat'}, 
456
+                'Boots of the Shadow Flame',
457
+                { class: 'Rogue', specname: 'Combat' },
417
                 undefined, 2, "hit bias"
458
                 undefined, 2, "hit bias"
418
             ),
459
             ),
419
             makePrio(
460
             makePrio(
420
-                'Boots of the Shadow Flame', 
421
-                {class:'Rogue', specname:'Subtlety'}, 
461
+                'Boots of the Shadow Flame',
462
+                { class: 'Rogue', specname: 'Subtlety' },
422
                 undefined, 2, "hit bias"
463
                 undefined, 2, "hit bias"
423
             ),
464
             ),
424
             makePrio(
465
             makePrio(
425
-                'Boots of the Shadow Flame', 
426
-                {class:'Druid', specname:'Feral (DPS)'}, 
466
+                'Boots of the Shadow Flame',
467
+                { class: 'Druid', specname: 'Feral (DPS)' },
427
                 undefined, 2, "hit bias"
468
                 undefined, 2, "hit bias"
428
             ),
469
             ),
429
 
470
 
430
             makePrio(
471
             makePrio(
431
-                'Neltharion\'s Tear', 
432
-                {class:'Warlock', specname:'Demonology'}, 
472
+                'Neltharion\'s Tear',
473
+                { class: 'Warlock', specname: 'Demonology' },
433
                 undefined, 4, "hit bias"
474
                 undefined, 4, "hit bias"
434
             ),
475
             ),
435
             makePrio(
476
             makePrio(
436
-                'Neltharion\'s Tear', 
437
-                {class:'Warlock', specname:'Affliction'}, 
477
+                'Neltharion\'s Tear',
478
+                { class: 'Warlock', specname: 'Affliction' },
438
                 undefined, 4, "hit bias"
479
                 undefined, 4, "hit bias"
439
             ),
480
             ),
440
             makePrio(
481
             makePrio(
441
-                'Neltharion\'s Tear', 
442
-                {class:'Warlock', specname:'Destruction'}, 
482
+                'Neltharion\'s Tear',
483
+                { class: 'Warlock', specname: 'Destruction' },
443
                 undefined, 4, "hit bias"
484
                 undefined, 4, "hit bias"
444
             ),
485
             ),
445
             makePrio(
486
             makePrio(
446
-                'Neltharion\'s Tear', 
447
-                {class:'Mage', specname:'Arcane'}, 
487
+                'Neltharion\'s Tear',
488
+                { class: 'Mage', specname: 'Arcane' },
448
                 undefined, 2, "hit bias"
489
                 undefined, 2, "hit bias"
449
             ),
490
             ),
450
             makePrio(
491
             makePrio(
451
-                'Neltharion\'s Tear', 
452
-                {class:'Mage', specname:'Frost'}, 
492
+                'Neltharion\'s Tear',
493
+                { class: 'Mage', specname: 'Frost' },
453
                 undefined, 2, "hit bias"
494
                 undefined, 2, "hit bias"
454
             ),
495
             ),
455
             makePrio(
496
             makePrio(
456
-                'Neltharion\'s Tear', 
457
-                {class:'Mage', specname:'Fire'}, 
497
+                'Neltharion\'s Tear',
498
+                { class: 'Mage', specname: 'Fire' },
458
                 undefined, 2, "hit bias"
499
                 undefined, 2, "hit bias"
459
             ),
500
             ),
460
 
501
 
461
             makePrio(
502
             makePrio(
462
-                'Cloak of Draconic Might', 
463
-                {class:'Warrior', specname:'Fury'}, 
503
+                'Cloak of Draconic Might',
504
+                { class: 'Warrior', specname: 'Fury' },
464
                 undefined, 2, "str-to-ap bias"
505
                 undefined, 2, "str-to-ap bias"
465
             ),
506
             ),
466
             makePrio(
507
             makePrio(
467
-                'Cloak of Draconic Might', 
468
-                {class:'Druid', specname:'Feral (DPS)'}, 
469
-                undefined, 2, "str-to-ap bias"
508
+                'Cloak of Draconic Might',
509
+                { class: 'Druid', specname: 'Feral (DPS)' },
510
+                undefined, 1, "str-to-ap bias"
470
             ),
511
             ),
471
-        ])
472
-
473
-
474
-        const user = Object.values(users)[0]
475
-        adminClient.managePriorities.setPriority(T1[0], {
476
-            race: user.character.race,
477
-            specid: user.character.specid,
478
-            modifier: 1,
479
-            description:'AAA'
480
-        }).then(() => {
481
-            adminClient.managePriorities.setPriority(T1[0], {
482
-                race: user.character.race,
483
-                specid: undefined,
484
-                modifier: 2,
485
-                description:'BBB'
486
-            }).then(()=>{
487
-                adminClient.managePriorities.setPriority(T1[0], {
488
-                    race: undefined,
489
-                    specid: user.character.specid,
490
-                    modifier: 3,
491
-                    description:'CCC'
492
-                }).then(()=>{
493
-                    client.ItemManager.calculatePriorities(T1[0], user.character).then(sum => {
494
-                        if(sum === 6)
495
-                            done()
496
-                    })
497
-                })
512
+        ]).then(() => {
513
+            const user = Object.values(users)[0]
514
+            client.ItemManager.calculatePriorities("Maladath, Runed Blade of the Black Flight", user.character).then(sum => {
515
+                if (sum === 3)
516
+                    done()
517
+                else
518
+                    console.log("Expected prio on maladath to be 4, but was:", sum, user.character);
498
             })
519
             })
520
+
499
         })
521
         })
500
     })
522
     })
501
 
523
 
502
-    it('buy token', (done)=>{
503
-        Promise.all(Object.values(users).map(async (user) =>{
504
-            const itemname = T1[0]//T1[Math.floor(T1.length*Math.random())]
524
+    it('buy token', (done) => {
525
+        Promise.all(Object.values(users).map(async (user) => {
526
+            const itemname = "Maladath, Runed Blade of the Black Flight" //T1[Math.floor(T1.length*Math.random())]
505
             const modifier = await client.ItemManager.calculatePriorities(itemname, user.character)
527
             const modifier = await client.ItemManager.calculatePriorities(itemname, user.character)
506
 
528
 
507
             const token = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
529
             const token = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
508
             users[user.account.username].item = itemname
530
             users[user.account.username].item = itemname
509
-            
510
-            if(!token) return false
511
-            return modifier+1 === token.level
531
+
532
+            if (!token) return false
533
+            return modifier + 1 === token.level
512
         })).then(success => {
534
         })).then(success => {
513
-            if(success.reduce((prev, curr)=>prev&&curr, true)) done()
535
+            if (success.reduce((prev, curr) => prev && curr, true)) done()
514
         })
536
         })
515
     })
537
     })
516
 
538
 
517
-    it('not buy token without currency', (done)=>{
539
+    it('not buy token without currency', (done) => {
518
         const user = Object.values(users)[0]
540
         const user = Object.values(users)[0]
519
-        const itemname = T1[0]
541
+        const itemname = "Maladath, Runed Blade of the Black Flight"
520
         client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!).then(token => {
542
         client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!).then(token => {
521
-            if(!token) 
543
+            if (!token)
522
                 done()
544
                 done()
523
             else {
545
             else {
524
                 console.log("Unexpected token", token);
546
                 console.log("Unexpected token", token);
526
         })
548
         })
527
     })
549
     })
528
 
550
 
529
-    it('upgrade token', (done)=>{
551
+    it('upgrade token', (done) => {
530
         const user = Object.values(users)[0]
552
         const user = Object.values(users)[0]
531
-        const itemname = T1[0]
532
-
533
-        adminClient.softreserveCurrency.incrementCurrency(user.account, raids[0].tier, 2).then(async ()=>{
534
-            const item = await client.ItemManager.getItem(itemname)
553
+        const itemname = "Maladath, Runed Blade of the Black Flight"
554
+        client.ItemManager.getItem(itemname).then(async item => {
555
+            await adminClient.softreserveCurrency.incrementCurrency(user.account, item.tier, 2)
535
             const before = await client.ItemManager.getToken(user.character, item)
556
             const before = await client.ItemManager.getToken(user.character, item)
536
-            
537
-            if(!before || before.level !== 7) {
538
-                console.log("expected level to be 7", before);
557
+
558
+            if (!before || before.level !== 4) {
559
+                console.log("expected level to be 4", before ? before.level : '?');
539
                 return
560
                 return
540
             }
561
             }
541
-            
562
+
542
             await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
563
             await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
543
             const after = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
564
             const after = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
544
 
565
 
545
-            if(!after || after.level !== 9) {
546
-                console.log("expected level to be 9", after);
566
+            if (!after || after.level !== 6) {
567
+                console.log("expected level after to be 6", after ? after.level : '?');
547
                 return
568
                 return
548
             }
569
             }
549
             done()
570
             done()
552
 
573
 
553
     it('should buy more tokens', (done) => {
574
     it('should buy more tokens', (done) => {
554
         Promise.all(Object.values(users).map(async (user) => {
575
         Promise.all(Object.values(users).map(async (user) => {
555
-            await adminClient.softreserveCurrency.incrementCurrency(user.account,raids[0].tier, 1)
576
+            await adminClient.softreserveCurrency.incrementCurrency(user.account, raids[0].tier, 1)
556
             return await client.ItemManager
577
             return await client.ItemManager
557
-            .buyToken(
558
-                user.auth.token.value, 
559
-                user.character.charactername, 
560
-                T1[Math.floor(T1.length*Math.random())],
561
-                user.signup!
562
-            )
578
+                .buyToken(
579
+                    user.auth.token.value,
580
+                    user.character.charactername,
581
+                    T2[Math.floor(T2.length * Math.random())],
582
+                    user.signup!
583
+                )
563
         })).then(_ => {
584
         })).then(_ => {
564
             done()
585
             done()
565
         })
586
         })
574
     })
595
     })
575
 
596
 
576
     it('start raid', (done) => {
597
     it('start raid', (done) => {
577
-        client.RaidManager.getRaids().then((r)=>{
598
+        client.RaidManager.getRaids().then((r) => {
578
             adminClient.manageRaid.startRaid(raids[0]).then(async data => {
599
             adminClient.manageRaid.startRaid(raids[0]).then(async data => {
579
                 const dbRaids = await client.RaidManager.getRaids()
600
                 const dbRaids = await client.RaidManager.getRaids()
580
-                if(dbRaids.length === 0){
601
+                if (dbRaids.length === 0) {
581
                     await client.UserManager.getUser(testAccounts[0].name).then(dbUser => {
602
                     await client.UserManager.getUser(testAccounts[0].name).then(dbUser => {
582
-                        if(dbUser && dbUser.MC === 1){
603
+                        if (dbUser && dbUser.BWL === 1) {
583
                             adminClient.signup.getSignups(raids[0]).then(signups => {
604
                             adminClient.signup.getSignups(raids[0]).then(signups => {
584
-                                if(signups.length === 0){
605
+                                if (signups.length === 0) {
585
                                     done()
606
                                     done()
586
-                                }else{
607
+                                } else {
587
                                     console.log(signups);
608
                                     console.log(signups);
588
                                 }
609
                                 }
589
                             })
610
                             })
590
                         }
611
                         }
591
-                        else{
612
+                        else {
592
                             console.log("Bad user currency", dbUser);
613
                             console.log("Bad user currency", dbUser);
593
                         }
614
                         }
594
                     })
615
                     })
600
     it('reset system', (done) => {
621
     it('reset system', (done) => {
601
         adminClient.reset.wipeCurrencyAndItems().then(() => {
622
         adminClient.reset.wipeCurrencyAndItems().then(() => {
602
             client.UserManager.getUser(testAccounts[0].name).then(user => {
623
             client.UserManager.getUser(testAccounts[0].name).then(user => {
603
-                if(user && user.MC === 1){
604
-                    client.ItemManager.getTokens(users[testAccounts[0].name.toLowerCase()].character, ['MC']).then(tokens => {
605
-                        if(tokens!.length === 0){
624
+                if (user && user.MC === 1) {
625
+                    client.ItemManager.getTokens(users[testAccounts[0].name.toLowerCase()].character, ['BWL']).then(tokens => {
626
+                        if (tokens!.length === 0) {
606
                             done()
627
                             done()
607
-                        }else{
628
+                        } else {
608
                             console.log(tokens);
629
                             console.log(tokens);
609
                         }
630
                         }
610
                     })
631
                     })
611
-                }else{
632
+                } else {
612
                     console.log(user)
633
                     console.log(user)
613
                 }
634
                 }
614
             })
635
             })
615
         })
636
         })
616
     })
637
     })
617
 
638
 
618
-    it('implements loot system correctly', (done)=>{
639
+    it('implements loot system correctly', (done) => {
619
         const ONE_WEEK = 4800000000
640
         const ONE_WEEK = 4800000000
620
-        
621
-        const Raid = (week:number, tier:string) => {
622
-                return <Raid>{
623
-                description: tier+" Test raid 1",
641
+
642
+        const Raid = (week: number, tier: string) => {
643
+            return <Raid>{
644
+                description: tier + " Test raid 1",
624
                 title: tier,
645
                 title: tier,
625
-                start: (week*ONE_WEEK + Date.now()).toString(),
646
+                start: (week * ONE_WEEK + Date.now()).toString(),
626
                 tier: tier
647
                 tier: tier
627
             }
648
             }
628
         }
649
         }
629
         const user = Object.values(users)[0]
650
         const user = Object.values(users)[0]
630
         const createRaid = adminClient.manageRaid.createRaid
651
         const createRaid = adminClient.manageRaid.createRaid
631
-        const sign = async (raid:Raid, late = false) => await adminClient.signup.sign(user.auth.token.value, user.character, raid, late)
652
+        const sign = async (raid: Raid, late = false) => await adminClient.signup.sign(user.auth.token.value, user.character, raid, late)
632
         const buyToken = async (signup: Signup, itemname: string) => await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, signup)
653
         const buyToken = async (signup: Signup, itemname: string) => await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, signup)
654
+        const getCurrency = async (tier: Tiers) => {
655
+            const dbUser = await client.UserManager.getUser(user.account.username)
656
+            return dbUser[tier]
657
+        }
633
 
658
 
634
-        createRaid(Raid(0, 'MC')).then(async (MC0:Raid) => {
635
-            const T1_0 = await client.ItemManager.getItem(T1[0])
659
+        createRaid(Raid(0, 'BWL')).then(async (BWL0: Raid) => {
660
+            const T2_0 = await client.ItemManager.getItem(T2[0])
636
             //const BWL0 = await createRaid(Raid(0, 'BWL'))
661
             //const BWL0 = await createRaid(Raid(0, 'BWL'))
637
-            const signupMC0 = await sign(MC0)
638
-            let token = await buyToken(signupMC0, T1[0])
639
-            if(!token){
640
-                console.log(MC0, signupMC0)
641
-                done("No token created")
662
+            const signupBWL0 = await sign(BWL0)
663
+            let BWL = await getCurrency(BWL0.tier)
664
+            let token = await buyToken(signupBWL0, T2[0])
665
+            const BWLAfter = await getCurrency(BWL0.tier)
666
+
667
+            if (!token
668
+                || BWL - BWLAfter != 1) {
669
+                console.log("Bad Token status", BWL0, signupBWL0, BWL, BWLAfter)
670
+                done(new Error("Bad Token status 0"))
642
                 return
671
                 return
643
             }
672
             }
644
 
673
 
645
-            let reserves = await client.ItemManager.getTokens(user.character, [MC0.tier], true)
646
-            let streaks = await client.ItemManager.getTokens(user.character, [MC0.tier], false)
647
-            if(reserves!.length != 1 
648
-            || streaks!.length != 0
649
-            || reserves![0].itemname !== T1_0.itemname
650
-            || reserves![0].level !== 7){
651
-                console.log(reserves, streaks);
652
-                done("Bad token status")
674
+            let reserves = await client.ItemManager.getTokens(user.character, [BWL0.tier], true)
675
+            let streaks = await client.ItemManager.getTokens(user.character, [BWL0.tier], false)
676
+            if (reserves!.length != 1
677
+                || streaks!.length != 0
678
+                || reserves![0].itemname !== T2_0.itemname
679
+                || reserves![0].level !== 1) {
680
+                console.log("Bad Token status 1", reserves, streaks);
681
+                done(new Error("Bad Token status"))
682
+                return
683
+            }
684
+            await adminClient.manageRaid.startRaid(BWL0)
685
+            reserves = await client.ItemManager.getTokens(user.character, [BWL0.tier], true)
686
+            streaks = await client.ItemManager.getTokens(user.character, [BWL0.tier], false)
687
+            if (reserves!.length != 0
688
+                || streaks!.length != 1
689
+                || streaks![0].itemname !== T2[0]
690
+                || streaks![0].level !== 1) {
691
+                console.log("Bad Token status", reserves, streaks);
692
+                done(new Error("Bad Token status 2"))
653
                 return
693
                 return
654
             }
694
             }
655
-            await adminClient.manageRaid.startRaid(MC0)
656
-            reserves = await client.ItemManager.getTokens(user.character, [MC0.tier], true)
657
-            streaks = await client.ItemManager.getTokens(user.character, [MC0.tier], false)
658
-            if(reserves!.length != 0 
659
-            || streaks!.length != 1
660
-            || streaks![0].itemname !== T1[0]
661
-            || streaks![0].level !== 7){
662
-                console.log(reserves, streaks);
663
-                done("Bad token status")
695
+
696
+            const BWL1 = await createRaid(Raid(1, 'BWL'))
697
+
698
+            let signupBWL1 = await sign(BWL1)
699
+            BWL = await getCurrency(BWL1.tier)
700
+            await adminClient.manageRaid.adminUnsign(user.character, BWL1)
701
+            let afterUnsign = await getCurrency(BWL1.tier)
702
+            if (BWL !== afterUnsign) {
703
+                console.log("Expected currency to be equal", BWL, afterUnsign)
704
+                done(new Error("Expected currency to be equal"))
664
                 return
705
                 return
665
             }
706
             }
666
 
707
 
667
-            const MC1 = await createRaid(Raid(1, 'MC'))
668
-            const signupMC1 = await sign(MC1)
669
-            token = await buyToken(signupMC1, T1[1])
670
-            reserves = await client.ItemManager.getTokens(user.character, [MC1.tier], true)
671
-            streaks = await client.ItemManager.getTokens(user.character, [MC1.tier], false)
672
-            if(reserves!.length != 1 
673
-            || streaks!.length != 0
674
-            || reserves![0].itemname !== T1[1]
675
-            || reserves![0].level !== 1){
676
-                console.log(reserves, streaks);
677
-                done("Bad token status")
708
+            signupBWL1 = await sign(BWL1)
709
+            BWL = await getCurrency(BWL1.tier)
710
+            await buyToken(signupBWL1, T2[1])
711
+            await adminClient.manageRaid.adminUnsign(user.character, BWL1)
712
+            afterUnsign = await getCurrency(BWL1.tier)
713
+            if (BWL !== afterUnsign) {
714
+                console.log("Expected currency to be equal", BWL, afterUnsign)
715
+                done(new Error("Expected currency to be equal"))
716
+                return
717
+            }
718
+
719
+            signupBWL1 = await sign(BWL1)
720
+            await buyToken(signupBWL1, T2[1])
721
+            reserves = await client.ItemManager.getTokens(user.character, [BWL1.tier], true)
722
+            streaks = await client.ItemManager.getTokens(user.character, [BWL1.tier], false)
723
+            if (reserves!.length != 1
724
+                || streaks!.length != 0
725
+                || reserves![0].itemname !== T2[1]
726
+                || reserves![0].level !== 1) {
727
+                console.log("Bad Token status", reserves, streaks);
728
+                done(new Error("Bad Token status 3"))
729
+                return
730
+            }
731
+
732
+            BWL = await getCurrency(BWL1.tier)
733
+            const data = await adminClient.manageRaid.startRaid(BWL1)
734
+
735
+            const afterStart = await getCurrency(BWL1.tier)
736
+            if (BWL != 0 || afterStart != 1) {
737
+                console.log("Wrong currency values", BWL, afterStart)
738
+                done(new Error("Wrong currency values"))
678
                 return
739
                 return
679
             }
740
             }
680
 
741
 
682
 
743
 
683
         }).catch(e => {
744
         }).catch(e => {
684
             console.log(e);
745
             console.log(e);
685
-            
746
+
686
             done(e)
747
             done(e)
687
         })
748
         })
688
     })
749
     })

Loading…
Cancel
Save