Browse Source

working buytoken (untested)

master
peter 5 years ago
parent
commit
59f518679e
37 changed files with 345 additions and 220 deletions
  1. 3
    2
      package.json
  2. 4
    3
      src/backend/Components/Item/Interface.ts
  3. 66
    59
      src/backend/Components/Item/ItemManager.ts
  4. 28
    28
      src/backend/Components/Raid/RaidManager.ts
  5. 5
    4
      src/backend/Components/User/Interface.ts
  6. 24
    16
      src/backend/Components/User/UserManager.ts
  7. 2
    2
      src/backend/Types/Items.ts
  8. 2
    0
      src/backend/Types/Types.ts
  9. 5
    2
      src/frontend/src/app/@theme/components/header/chat.component.ts
  10. 1
    7
      src/frontend/src/app/frontcraft/pages/character/character.component.html
  11. 2
    1
      src/frontend/src/app/frontcraft/pages/character/character.component.ts
  12. 4
    0
      src/frontend/src/app/frontcraft/pages/pages.module.ts
  13. 1
    0
      src/frontend/src/app/frontcraft/pages/raid/archive.component.ts
  14. 7
    4
      src/frontend/src/app/frontcraft/pages/raid/raid.component.html
  15. 10
    6
      src/frontend/src/app/frontcraft/pages/raid/raid.component.ts
  16. 4
    0
      src/frontend/src/app/frontcraft/pages/raids/createraid.component.html
  17. 5
    0
      src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts
  18. 1
    1
      src/frontend/src/app/frontcraft/pages/raids/raids.component.html
  19. 1
    9
      src/frontend/src/app/frontcraft/pages/rules/rules.component.html
  20. 69
    47
      src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts
  21. 30
    0
      src/frontend/src/app/frontcraft/pages/shop/item.component.ts
  22. 2
    8
      src/frontend/src/app/frontcraft/pages/shop/itemselect.component.html
  23. 3
    1
      src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts
  24. 4
    6
      src/frontend/src/app/frontcraft/pages/shop/shop.component.html
  25. 7
    2
      src/frontend/src/app/frontcraft/pages/shop/shop.component.ts
  26. 26
    0
      src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts
  27. 6
    1
      src/frontend/src/app/frontcraft/pages/user/user.component.html
  28. 2
    1
      src/frontend/src/app/frontcraft/pages/user/user.component.ts
  29. BIN
      src/frontend/src/assets/images/aq20.png
  30. BIN
      src/frontend/src/assets/images/aq40.png
  31. BIN
      src/frontend/src/assets/images/bwl.png
  32. BIN
      src/frontend/src/assets/images/mc.png
  33. BIN
      src/frontend/src/assets/images/naxx.png
  34. BIN
      src/frontend/src/assets/images/null.png
  35. BIN
      src/frontend/src/assets/images/ony.png
  36. BIN
      src/frontend/src/assets/images/zg.png
  37. 21
    10
      test/backendTest.ts

+ 3
- 2
package.json View File

4
   "version": "1.0.0",
4
   "version": "1.0.0",
5
   "scripts": {
5
   "scripts": {
6
     "tsc": "tsc",
6
     "tsc": "tsc",
7
-    "start": "npm run build; node lib/src/backend/Launcher.js",
7
+    "launch": "node lib/src/backend/Launcher.js",
8
+    "start": "npm run build; npm run launch",
8
     "start-backend": "npm run build-backend; node lib/src/backend/Launcher.js",
9
     "start-backend": "npm run build-backend; node lib/src/backend/Launcher.js",
9
-    "build": "npm run clean; npm run build-backend; npm run build-frontend",
10
+    "build": "npm run build-backend; npm run build-frontend",
10
     "test": "npm run clean && npm run build-backend && mocha lib/test/backendTest.js",
11
     "test": "npm run clean && npm run build-backend && mocha lib/test/backendTest.js",
11
     "build-backend": "tsc;",
12
     "build-backend": "tsc;",
12
     "build-frontend": "mkdir dist; mkdir dist/static; npm run build-dashboard;",
13
     "build-frontend": "mkdir dist; mkdir dist/static; npm run build-dashboard;",

+ 4
- 3
src/backend/Components/Item/Interface.ts View File

1
 import { Item, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types"
1
 import { Item, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types"
2
+import { Tiers } from "../../Types/Items"
2
 
3
 
3
 export class IItemManager{
4
 export class IItemManager{
4
     getItems: () => Promise<Item[]>
5
     getItems: () => Promise<Item[]>
5
     fetchItem: (name:string) => Promise<Item>
6
     fetchItem: (name:string) => Promise<Item>
6
-    buyToken: (usertoken: string, charactername:string, itemname:string, signup:Signup) => Promise<(SRToken & Character & Item) | void>
7
+    buyToken: (usertoken: string, charactername:string, itemname:string, signup:Signup) => Promise<(SRToken & Character & Item) | undefined>
7
     setPriority: (itemname:string, priority: any) => Promise<void>
8
     setPriority: (itemname:string, priority: any) => Promise<void>
8
     calculatePriorities: (itemname: string, character:Character) => Promise<number>
9
     calculatePriorities: (itemname: string, character:Character) => Promise<number>
9
     deletePriority: (priority:SRPriority) => Promise<void>
10
     deletePriority: (priority:SRPriority) => Promise<void>
10
-    getTokens: (character:Character, valid?:boolean) => Promise<SRToken[]>
11
-    getToken: (character:Character, item:Item, valid?:boolean) => Promise<(SRToken & Character & Item) | void>
11
+    getTokens: (character:Character, tiers: Tiers[], valid?:boolean) => Promise<(SRToken & Character & Item)[] | undefined>
12
+    getToken: (character:Character, item:Item, valid?:boolean) => Promise<(SRToken & Character & Item) | undefined>
12
     getAllPriorities: () => Promise<(SRPriority & Spec & Item)[]>
13
     getAllPriorities: () => Promise<(SRPriority & Spec & Item)[]>
13
     wipeCurrencyAndItems: () => Promise<void>
14
     wipeCurrencyAndItems: () => Promise<void>
14
 }
15
 }

+ 66
- 59
src/backend/Components/Item/ItemManager.ts View File

1
-import { T1, T2, allItems, _Tiers } from "../../Types/Items";
1
+import { T1, T2, 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";
54
     wipeCurrencyAndItems = async () => {
54
     wipeCurrencyAndItems = async () => {
55
         await Promise.all([
55
         await Promise.all([
56
             this.userManager.wipeCurrency(),
56
             this.userManager.wipeCurrency(),
57
-            this.admin.knex('tokens').where(true).del()
57
+            Promise.all(_Tiers.map(tier => this.admin.knex(tier+'tokens').where(true).del()))
58
         ])
58
         ])
59
     }
59
     }
60
 
60
 
84
 
84
 
85
     getTableDefinitions(): TableDefiniton[] {
85
     getTableDefinitions(): TableDefiniton[] {
86
         return [
86
         return [
87
-            {
88
-                name: 'tokens',
89
-                tableBuilder: (table) => {
90
-                    table.primary(['characterid', 'itemname'])
91
-                    table.integer("characterid")
92
-                    table.foreign("characterid").references("id").inTable('characters')
93
-                    table.string("itemname")
94
-                    table.foreign("itemname").references("itemname").inTable('items')
95
-                    table.string("signupid").nullable()
96
-                    table.foreign("signupid").references("id").inTable('signups').onDelete('SET NULL')
97
-                    table.integer("level").defaultTo(1)
87
+            ...['null',..._Tiers].map(tier => {
88
+                return {
89
+                    name: tier+'tokens',
90
+                    tableBuilder: (table) => {
91
+                        table.primary(['characterid', 'itemname'])
92
+                        table.integer("characterid")
93
+                        table.foreign("characterid").references("id").inTable('characters')
94
+                        table.string("itemname")
95
+                        table.foreign("itemname").references("itemname").inTable('items')
96
+                        table.string("signupid").nullable()
97
+                        table.foreign("signupid").references("id").inTable('signups').onDelete('SET NULL')
98
+                        table.integer("level").defaultTo(1)
99
+                    }
98
                 }
100
                 }
99
-            },{
101
+            }),{
100
                 name: 'priorities',
102
                 name: 'priorities',
101
                 tableBuilder: (table) => {
103
                 tableBuilder: (table) => {
102
                     table.increments('id').primary()
104
                     table.increments('id').primary()
121
             }]
123
             }]
122
     }
124
     }
123
 
125
 
124
-    buyToken = async (usertoken: string, charactername:string, itemname:string, signup: Signup): Promise<(SRToken & Character & Item) | void> => {
126
+    buyToken = async (usertoken: string, charactername:string, itemname:string, signup: Signup): Promise<(SRToken & Character & Item) | undefined> => {
125
         const record = this.userManager.getUserRecordByToken(usertoken)
127
         const record = this.userManager.getUserRecordByToken(usertoken)
126
         const character = await this.character.getCharacterByName(charactername)
128
         const character = await this.character.getCharacterByName(charactername)
127
 
129
 
130
         const item = await this.getItem(itemname)
132
         const item = await this.getItem(itemname)
131
         if(!item) return
133
         if(!item) return
132
 
134
 
133
-        const currency = await this.userManager.getCurrency(record.user)
135
+        const currency = await this.userManager.getCurrency(record.user, item.tier)
134
         if(currency < 1) return
136
         if(currency < 1) return
135
 
137
 
136
-        const shadowTokens = await this.getTokens(character, false)
137
-        const activeTokens = await this.getTokens(character, true)
138
+        const streaks = await this.getTokens(character, [item.tier], false)
139
+        const activeTokens = await this.getTokens(character, [item.tier], true)
138
 
140
 
139
-        await this.userManager.decrementCurrency(record.user, 1)
141
+        await this.userManager.decrementCurrency(record.user, item.tier, 1)
140
         const modifier = await this.calculatePriorities(itemname, character)
142
         const modifier = await this.calculatePriorities(itemname, character)
141
 
143
 
142
-        //tokens with deleted signups
143
-        if(shadowTokens.length > 0){
144
-            //token for current item
145
-            const matchingtoken = shadowTokens.find(token => token.itemname === itemname)
146
-            if(matchingtoken){
147
-                //update signupid and increment level
148
-                
149
-                
144
+        if(streaks.length > 0){
145
+            const myStreak = streaks.find(token => token.itemname === itemname)
146
+            if(myStreak){
150
 
147
 
148
+                //getLogger('ItemManager').debug('update signupid and increment level')
151
                 await this.admin
149
                 await this.admin
152
-                .knex('tokens')
150
+                .knex(item.tier+'tokens')
153
                 .where({
151
                 .where({
154
                     characterid: character.id,
152
                     characterid: character.id,
155
                     itemname: item.itemname
153
                     itemname: item.itemname
156
                 })
154
                 })
157
                 .update({
155
                 .update({
158
                     signupid: signup.id,
156
                     signupid: signup.id,
159
-                    level: matchingtoken.level+1
157
+                    level: myStreak.level+1
160
                 })
158
                 })
161
-                
162
-                await this.admin
163
-                .knex('tokens')
159
+
160
+            }
161
+
162
+            //getLogger('ItemManager').debug('delete streaks')
163
+            await Promise.all(streaks.map(async s => await this.admin
164
+                .knex(item.tier+'tokens')
164
                 .where({
165
                 .where({
166
+                    itemname: s.itemname,
165
                     characterid: character.id,
167
                     characterid: character.id,
166
-                    itemname: item.itemname,
167
                     signupid: null
168
                     signupid: null
168
-                }).del()
169
-                
169
+                })
170
+                .del()
171
+            ))
172
+            
173
+            if(myStreak)
170
                 return await this.getToken(character, item)
174
                 return await this.getToken(character, item)
171
-            }
172
         }
175
         }
173
 
176
 
174
-        const matchingtoken = activeTokens.find(token => token.itemname === itemname)
175
-        if(matchingtoken){
176
-            //power up token
177
+        const matchingReserve = activeTokens.find(token => token.itemname === itemname)
178
+        if(matchingReserve){
179
+            getLogger('ItemManager').debug('upgrade reserve')
177
             await this.admin
180
             await this.admin
178
-            .knex('tokens')
181
+            .knex(item.tier+'tokens')
179
             .increment('level')
182
             .increment('level')
180
             .where({
183
             .where({
181
                 signupid: signup.id,
184
                 signupid: signup.id,
183
                 itemname: item.itemname
186
                 itemname: item.itemname
184
             })
187
             })
185
         }else{
188
         }else{
189
+            getLogger('ItemManager').debug('new reserve')
186
             await this.admin
190
             await this.admin
187
-            .knex('tokens')
191
+            .knex(item.tier+'tokens')
188
             .insert({
192
             .insert({
189
                 characterid: character.id,
193
                 characterid: character.id,
190
                 itemname: item.itemname,
194
                 itemname: item.itemname,
257
         }).reduce((prev, curr) => prev+curr, 0)
261
         }).reduce((prev, curr) => prev+curr, 0)
258
     }
262
     }
259
 
263
 
260
-    getToken = async (character:Character, item:Item,valid=true): Promise<(SRToken & Character & Item) | void>=> {
264
+    getToken = async (character:Character, item:Item, valid=true): Promise<(SRToken & Character & Item) | undefined>=> {
261
         return await this.admin
265
         return await this.admin
262
-        .knex('tokens as t')
266
+        .knex(item.tier+'tokens as t')
263
         .select('*')
267
         .select('*')
264
         .join('characters as c', 'c.id', '=', 't.characterid')
268
         .join('characters as c', 'c.id', '=', 't.characterid')
265
         .join('items as i', 'i.itemname', '=', 't.itemname')
269
         .join('items as i', 'i.itemname', '=', 't.itemname')
277
         .first()
281
         .first()
278
     }
282
     }
279
 
283
 
280
-    getTokens = async (character:Character, valid=true) : Promise<(SRToken & Character & Item)[]> => {
281
-        return await this.admin
282
-        .knex('tokens as t')
283
-        .select('*')
284
-        .join('characters as c', 'c.id', '=', 't.characterid')
285
-        .join('items as i', 'i.itemname', '=', 't.itemname')
286
-        .where({
287
-            characterid: character.id,
288
-        })
289
-        .andWhere(function(){
290
-            if(valid){
291
-                this.whereNotNull('t.signupid')
292
-            }else{
293
-                this.whereNull('t.signupid')
294
-            }
295
-        })
284
+    getTokens = async (character:Character, tiers:Tiers[], valid=true) : Promise<(SRToken & Character & Item)[]> => {
285
+        const ret = await Promise.all(tiers.map(async tier => {
286
+            return await this.admin
287
+            .knex(tier+'tokens as t')
288
+            .select('*')
289
+            .join('characters as c', 'c.id', '=', 't.characterid')
290
+            .join('items as i', 'i.itemname', '=', 't.itemname')
291
+            .where({
292
+                characterid: character.id,
293
+            })
294
+            .andWhere(function(){
295
+                if(valid){
296
+                    this.whereNotNull('t.signupid')
297
+                }else{
298
+                    this.whereNull('t.signupid')
299
+                }
300
+            })
301
+        }))
302
+        return ret.flat()
296
     }
303
     }
297
 
304
 
298
     countItems = async() :Promise<number> => {
305
     countItems = async() :Promise<number> => {

+ 28
- 28
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 { SpecT } from "../../Types/PlayerSpecs";
13
 
12
 
14
 @Injectable(IRaidManager)
13
 @Injectable(IRaidManager)
15
 export class RaidManager
14
 export class RaidManager
126
 
125
 
127
     startRaid = async (raid:Raid) : Promise<RaidData> => {
126
     startRaid = async (raid:Raid) : Promise<RaidData> => {
128
         const archived = await this.archiveRaid(raid)
127
         const archived = await this.archiveRaid(raid)
129
-        delete archived.participants.late
130
-
128
+        
131
         const giveCurrency = async (b: Character) => {
129
         const giveCurrency = async (b: Character) => {
132
             const usr = await this.characterManager.getUserOfCharacter(b)
130
             const usr = await this.characterManager.getUserOfCharacter(b)
133
-            await this.userManager.incrementCurrency(usr, 1)
131
+            await this.userManager.incrementCurrency(usr, raid.tier, 1)
134
         }
132
         }
135
 
133
 
136
         await Promise.all([
134
         await Promise.all([
144
     archiveRaid = async (raid:Raid) : Promise<RaidData> => {
142
     archiveRaid = async (raid:Raid) : Promise<RaidData> => {
145
         const raidData = await this.getRaidData(raid)
143
         const raidData = await this.getRaidData(raid)
146
 
144
 
147
-        const tx = await this.admin.knex.transaction()
145
+        //const tx = await this.admin.knex.transaction()
148
 
146
 
149
         await this.admin.knex('archive')
147
         await this.admin.knex('archive')
150
-        .transacting(tx)
148
+        //.transacting(tx)
151
         .insert({
149
         .insert({
152
             id:raidData.id,
150
             id:raidData.id,
153
             raiddata: JSON.stringify(raidData)
151
             raiddata: JSON.stringify(raidData)
155
 
153
 
156
         await Promise.all(
154
         await Promise.all(
157
             Object.values(raidData.participants).flat().flatMap((signup) => this.admin
155
             Object.values(raidData.participants).flat().flatMap((signup) => this.admin
158
-                .knex('tokens')
159
-                .transacting(tx)
156
+                .knex(raid.tier+'tokens')
157
+                //.transacting(tx)
160
                 .where({
158
                 .where({
161
                     characterid: signup.characterid,
159
                     characterid: signup.characterid,
162
                     signupid: null
160
                     signupid: null
165
         ))
163
         ))
166
 
164
 
167
         await this.admin.knex('raids')
165
         await this.admin.knex('raids')
168
-        .transacting(tx)
166
+        //.transacting(tx)
169
         .where('id', '=', raid.id)
167
         .where('id', '=', raid.id)
170
         .del()
168
         .del()
171
-        await tx.commit()
169
+        //await tx.commit()
172
 
170
 
173
     
171
     
174
         const row = await this.admin.knex('archive')
172
         const row = await this.admin.knex('archive')
216
             healers:<(Signup&Character&Spec)[]>[],
214
             healers:<(Signup&Character&Spec)[]>[],
217
             tanks:<(Signup&Character&Spec)[]>[]
215
             tanks:<(Signup&Character&Spec)[]>[]
218
         }
216
         }
219
-        const tx = await this.admin.knex.transaction()
217
+        //const tx = await this.admin.knex.transaction()
220
 
218
 
221
         const subQuery = this.admin
219
         const subQuery = this.admin
222
         .knex('signups')
220
         .knex('signups')
231
 
229
 
232
         const raidInDb: Raid = await this.admin.knex('raids')
230
         const raidInDb: Raid = await this.admin.knex('raids')
233
         .select('*', subQuery)
231
         .select('*', subQuery)
234
-        .transacting(tx)
232
+        //.transacting(tx)
235
         .where('id','=',raid.id)
233
         .where('id','=',raid.id)
236
         .first()
234
         .first()
237
 
235
 
238
         const characterData: (Signup & Character & Spec)[] = await this.admin
236
         const characterData: (Signup & Character & Spec)[] = await this.admin
239
         .knex('signups as s')
237
         .knex('signups as s')
240
-        .transacting(tx)
238
+        //.transacting(tx)
241
         .select('s.id as id', 'charactername', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
239
         .select('s.id as id', 'charactername', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
242
         .join('raids as r', 's.raidid','=','r.id')
240
         .join('raids as r', 's.raidid','=','r.id')
243
         .join('characters as c', 's.characterid','=','c.id')
241
         .join('characters as c', 's.characterid','=','c.id')
259
 
257
 
260
         const tokenData: (Character & SRToken & Item)[] = await this.admin
258
         const tokenData: (Character & SRToken & Item)[] = await this.admin
261
         .knex('signups as s')
259
         .knex('signups as s')
262
-        .transacting(tx)
260
+        //.transacting(tx)
263
         .select('*', 's.id as id')
261
         .select('*', 's.id as id')
264
         .join('raids as r', 's.raidid','=','r.id')
262
         .join('raids as r', 's.raidid','=','r.id')
265
-        .where('r.id','=',raid.id)
263
+        .join('characters as c', 's.characterid','=','c.id')
264
+        .join(raidInDb.tier+'tokens as t', 't.characterid','=','c.id')
265
+        .join('items as i', 'i.itemname','=','t.itemname')
266
+        .where({
267
+            'r.id': raid.id,
268
+        })
266
         .andWhere(function(){
269
         .andWhere(function(){
267
             this.whereNotNull('t.signupid')
270
             this.whereNotNull('t.signupid')
268
         })
271
         })
269
-        .join('characters as c', 's.characterid','=','c.id')
270
-        .join('tokens as t', 't.characterid','=','c.id')
271
-        .join('items as i', 'i.itemname','=','t.itemname')
272
 
272
 
273
-        await tx.commit()
273
+        //await tx.commit()
274
 
274
 
275
         tokenData.forEach(data => {
275
         tokenData.forEach(data => {
276
             if(!raiddata.tokens[data.itemname])
276
             if(!raiddata.tokens[data.itemname])
313
         if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
313
         if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
314
             throw new Error("Bad Usertoken")
314
             throw new Error("Bad Usertoken")
315
         }
315
         }
316
-        const tx = await this.admin.knex.transaction()
316
+        //const tx = await this.admin.knex.transaction()
317
 
317
 
318
         const exists = await this.admin
318
         const exists = await this.admin
319
         .knex('signups')
319
         .knex('signups')
320
-        .transacting(tx)
320
+        //.transacting(tx)
321
         .select('*')
321
         .select('*')
322
         .where({
322
         .where({
323
             raidid: raid.id!,
323
             raidid: raid.id!,
328
         if(!exists){
328
         if(!exists){
329
             await this.admin
329
             await this.admin
330
             .knex('signups')
330
             .knex('signups')
331
-            .transacting(tx)
331
+            //.transacting(tx)
332
             .insert({
332
             .insert({
333
                 raidid: raid.id!,
333
                 raidid: raid.id!,
334
                 characterid: character.id!,
334
                 characterid: character.id!,
338
         }else{
338
         }else{
339
             await this.admin
339
             await this.admin
340
             .knex('signups')
340
             .knex('signups')
341
-            .transacting(tx)
341
+            //.transacting(tx)
342
             .where({
342
             .where({
343
                 id: exists.id 
343
                 id: exists.id 
344
             })
344
             })
349
                 benched: false,
349
                 benched: false,
350
             })
350
             })
351
         }
351
         }
352
-        await tx.commit()
352
+        //await tx.commit()
353
 
353
 
354
         return await this.admin
354
         return await this.admin
355
         .knex('signups')
355
         .knex('signups')
380
             "si.characterid": character.id!,
380
             "si.characterid": character.id!,
381
         }).first()
381
         }).first()
382
 
382
 
383
-        const tokens = await this.admin.knex('tokens as t')
383
+        const tokens = await this.admin.knex(raid.tier+'tokens as t')
384
         .where('t.signupid', signup.id)
384
         .where('t.signupid', signup.id)
385
         
385
         
386
         //check if token has to be deleted
386
         //check if token has to be deleted
387
         Promise.all(
387
         Promise.all(
388
             tokens.map(async token => {
388
             tokens.map(async token => {
389
-                await this.userManager.incrementCurrency(user, 1)       
389
+                await this.userManager.incrementCurrency(user, raid.tier, 1)       
390
                 const prio = await this.itemManager.calculatePriorities(token.itemname, character)
390
                 const prio = await this.itemManager.calculatePriorities(token.itemname, character)
391
                 if(token.level <= prio+1){
391
                 if(token.level <= prio+1){
392
-                    await this.admin.knex('tokens')
392
+                    await this.admin.knex(raid.tier+'tokens')
393
                     .where({
393
                     .where({
394
                         characterid: character.id,
394
                         characterid: character.id,
395
                         itemname: token.itemname
395
                         itemname: token.itemname
396
                     }).del()
396
                     }).del()
397
                 }else{
397
                 }else{
398
-                    await this.admin.knex('tokens')
398
+                    await this.admin.knex(raid.tier+'tokens')
399
                     .where({
399
                     .where({
400
                         characterid: character.id,
400
                         characterid: character.id,
401
                         itemname: token.itemname
401
                         itemname: token.itemname

+ 5
- 4
src/backend/Components/User/Interface.ts View File

1
 import { Auth, Rank, User, RPCPermission, UserRecord } from "../../Types/Types"
1
 import { Auth, Rank, User, RPCPermission, UserRecord } from "../../Types/Types"
2
+import { Tiers } from "../../Types/Items"
2
 
3
 
3
 export class IUserManager{
4
 export class IUserManager{
4
     login: (username:string, pwHash:string) => Promise<Auth>
5
     login: (username:string, pwHash:string) => Promise<Auth>
11
     getUserRecordByToken: (tokenValue: string) => UserRecord | void
12
     getUserRecordByToken: (tokenValue: string) => UserRecord | void
12
     getUser: (username: string) => Promise<User | void>
13
     getUser: (username: string) => Promise<User | void>
13
 
14
 
14
-    decrementCurrency: (user: User, value: number) => Promise<void>
15
-    incrementCurrency: (user: User, value: number) => Promise<void>
16
-    setCurrency: (user: User, value: number) => Promise<void>
17
-    getCurrency: (user:User) => Promise<number>
15
+    decrementCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
16
+    incrementCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
17
+    setCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
18
+    getCurrency: (user:User, tier:Tiers) => Promise<number>
18
     changeRank: (user:User, rank: Rank) => Promise<User>
19
     changeRank: (user:User, rank: Rank) => Promise<User>
19
     wipeCurrency: () => Promise<void>
20
     wipeCurrency: () => Promise<void>
20
 }
21
 }

+ 24
- 16
src/backend/Components/User/UserManager.ts View File

12
 import { IUserManager } from "./Interface";
12
 import { IUserManager } from "./Interface";
13
 import { getLogger, Logger } from "log4js";
13
 import { getLogger, Logger } from "log4js";
14
 import { saltedHash } from "../../Util/hash";
14
 import { saltedHash } from "../../Util/hash";
15
+import { _Tiers, Tiers } from "../../Types/Items";
15
 
16
 
16
 const uuid = require('uuid/v4')
17
 const uuid = require('uuid/v4')
17
 
18
 
97
                 table.string("username").notNullable().unique()
98
                 table.string("username").notNullable().unique()
98
                 table.string("pwhash").notNullable()
99
                 table.string("pwhash").notNullable()
99
                 table.string("rank").notNullable()
100
                 table.string("rank").notNullable()
100
-                table.string("email").nullable().unique()
101
-                table.integer("currency").defaultTo(1)
101
+                _Tiers.forEach(tier => {
102
+                    table.integer(tier).defaultTo(1)
103
+                })
102
             }
104
             }
103
         },{
105
         },{
104
             name: 'rpcpermissions',
106
             name: 'rpcpermissions',
286
     }
288
     }
287
 
289
 
288
     wipeCurrency = async () => {
290
     wipeCurrency = async () => {
289
-        await this.admin.knex('users')
290
-        .update({currency: 0})
291
+        await Promise.all(_Tiers.map(tier => {
292
+            const update = {}
293
+            update[tier] = 1
294
+    
295
+            return this.admin.knex('users')
296
+            .update(update)
297
+        }))
291
     }
298
     }
292
 
299
 
293
     login = async(username:string, pwHash:string) : Promise<Auth> => {
300
     login = async(username:string, pwHash:string) : Promise<Auth> => {
405
         return token
412
         return token
406
     }
413
     }
407
 
414
 
408
-    getCurrency = async(user:User) : Promise<number> => { 
415
+    getCurrency = async(user:User, tier?: Tiers) : Promise<number> => { 
416
+        if(!tier) return 0
409
         const usr : User = await this.admin
417
         const usr : User = await this.admin
410
         .knex('users')
418
         .knex('users')
411
         .where('username', '=', user.username)
419
         .where('username', '=', user.username)
412
         .select('*')
420
         .select('*')
413
         .first()
421
         .first()
414
 
422
 
415
-        return usr.currency!
423
+        return usr[tier]!
416
     }
424
     }
417
 
425
 
418
-    decrementCurrency = async (user: User, value = 1) => {
419
-        if(value < 1) return
426
+    decrementCurrency = async (user: User, tier?: Tiers, value = 1) => {
427
+        if(!tier || value < 1) return
420
 
428
 
421
         const usr : User = await this.admin
429
         const usr : User = await this.admin
422
         .knex('users')
430
         .knex('users')
424
         .select('*')
432
         .select('*')
425
         .first()
433
         .first()
426
 
434
 
427
-        if(!usr || usr.currency! <= 0) return
435
+        if(!usr || usr[tier]! <= 0) return
428
 
436
 
429
         await this.admin
437
         await this.admin
430
         .knex('users')
438
         .knex('users')
431
         .where('id', '=', user.id)
439
         .where('id', '=', user.id)
432
-        .decrement('currency', value)
440
+        .decrement(tier, value)
433
     }
441
     }
434
 
442
 
435
-    incrementCurrency = async (user: User, value = 1) => {
436
-        if(value < 1) return
443
+    incrementCurrency = async (user: User, tier: Tiers, value = 1) => {
444
+        if(!tier || value < 1) return
437
         await this.admin
445
         await this.admin
438
         .knex('users')
446
         .knex('users')
439
         .where('id', '=', user.id)
447
         .where('id', '=', user.id)
440
-        .increment('currency', value)
448
+        .increment(tier, value)
441
     }
449
     }
442
 
450
 
443
-    setCurrency = async (user: User, value: number) => {
444
-        if(value < 0) return
451
+    setCurrency = async (user: User, tier?:Tiers, value = 0) => {
452
+        if(!tier || value < 0) return
445
         await this.admin
453
         await this.admin
446
         .knex('users')
454
         .knex('users')
447
         .where('id', '=', user.id)
455
         .where('id', '=', user.id)
448
-        .update('currency', value)
456
+        .update(tier, value)
449
     }
457
     }
450
 
458
 
451
 
459
 

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

1
-export type Tiers = "MC" | 'BWL' | 'ZG' | 'AQ20' | 'AQ40' | 'Naxx'
2
-export const _Tiers = ["MC", 'BWL', 'ZG', 'AQ20', 'AQ40', 'Naxx']
1
+export type Tiers =  "MC" | 'BWL' | 'ZG' | 'AQ20' | 'AQ40' | 'Naxx'
2
+export const _Tiers:Tiers[] = ["MC", 'BWL', 'ZG', 'AQ20', 'AQ40', 'Naxx']
3
 
3
 
4
 export const T1 = [
4
 export const T1 = [
5
 "Robe of Volatile Power",
5
 "Robe of Volatile Power",

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

94
     pwhash: string
94
     pwhash: string
95
     rank: Rank
95
     rank: Rank
96
     currency?: number
96
     currency?: number
97
+} & {
98
+    [currency in Tiers]? : number
97
 }
99
 }
98
 
100
 
99
 export type Raid = {
101
 export type Raid = {

+ 5
- 2
src/frontend/src/app/@theme/components/header/chat.component.ts View File

10
                            [type]="text"
10
                            [type]="text"
11
                            [message]="msg.message"
11
                            [message]="msg.message"
12
                            [sender]="msg.sender"
12
                            [sender]="msg.sender"
13
-                           [date]="msg.date">
13
+                           [date]="msg.date"
14
+                           [reply]="msg.reply">
14
           </nb-chat-message>
15
           </nb-chat-message>
15
-          <nb-chat-form (send)="submit($event)" [dropFiles]="false">
16
+          <nb-chat-form 
17
+          (send)="submit($event)" 
18
+          [dropFiles]="false">
16
           </nb-chat-form>
19
           </nb-chat-form>
17
         </nb-chat>
20
         </nb-chat>
18
   `, 
21
   `, 

+ 1
- 7
src/frontend/src/app/frontcraft/pages/character/character.component.html View File

25
         <br/><br />
25
         <br/><br />
26
         <span *ngFor="let token of tokens">
26
         <span *ngFor="let token of tokens">
27
             [ {{token.level}} ]
27
             [ {{token.level}} ]
28
-            <a [ngStyle]="{'color':token.quality=='Epic'?'#a335ee':'#ff8000'}" 
29
-            target="_blank" 
30
-            [href]="token.url">
31
-            <img style="min-width: 25px; width: 2.25vw; max-width: 50px" 
32
-            [src]="'https://wow.zamimg.com/images/wow/icons/large/'+token.iconname+'.jpg'" />
33
-            {{token.itemname}}
34
-            </a><br />
28
+            <wowhead [item]="token"></wowhead><br />
35
         </span>
29
         </span>
36
     </nb-card-body>
30
     </nb-card-body>
37
 </nb-card>
31
 </nb-card>

+ 2
- 1
src/frontend/src/app/frontcraft/pages/character/character.component.ts View File

3
 import { ApiService as ApiService } from '../../services/login-api';
3
 import { ApiService as ApiService } from '../../services/login-api';
4
 import { Spec, User, Character } from '../../../../../../backend/Types/Types';
4
 import { Spec, User, Character } from '../../../../../../backend/Types/Types';
5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
+import { _Tiers } from '../../../../../../backend/Types/Items';
6
 
7
 
7
 @Component({
8
 @Component({
8
   selector: 'character',
9
   selector: 'character',
35
         if(char){
36
         if(char){
36
           this.color = getClassColor(char.class)
37
           this.color = getClassColor(char.class)
37
           this.char = char
38
           this.char = char
38
-          this.api.get('ItemManager').getTokens(this.char).then(tokens => {
39
+          this.api.get('ItemManager').getTokens(this.char, _Tiers, true).then(tokens => {
39
             this.tokens = tokens
40
             this.tokens = tokens
40
           })
41
           })
41
         }
42
         }

+ 4
- 0
src/frontend/src/app/frontcraft/pages/pages.module.ts View File

38
 import { NgxEchartsModule } from 'ngx-echarts';
38
 import { NgxEchartsModule } from 'ngx-echarts';
39
 import { FrontcraftCharactersComponent } from './characters/characters.component';
39
 import { FrontcraftCharactersComponent } from './characters/characters.component';
40
 import { FrontcraftBuyTokenComponent } from './shop/buytoken.component';
40
 import { FrontcraftBuyTokenComponent } from './shop/buytoken.component';
41
+import { FrontcraftItemComponent } from './shop/item.component';
42
+import { FrontcraftWowheadComponent } from './shop/wowhead.component';
41
 
43
 
42
 
44
 
43
 @NgModule({
45
 @NgModule({
81
     FrontcraftRulesComponent,
83
     FrontcraftRulesComponent,
82
     FrontcraftCreateRaidsComponent,
84
     FrontcraftCreateRaidsComponent,
83
     FrontcraftBuyTokenComponent,
85
     FrontcraftBuyTokenComponent,
86
+    FrontcraftWowheadComponent,
87
+    FrontcraftItemComponent
84
   ],
88
   ],
85
   entryComponents: [
89
   entryComponents: [
86
     FrontcraftItemSelectComponent,
90
     FrontcraftItemSelectComponent,

+ 1
- 0
src/frontend/src/app/frontcraft/pages/raid/archive.component.ts View File

13
     canSignup = false
13
     canSignup = false
14
     isSignedup = false
14
     isSignedup = false
15
     canManage = false
15
     canManage = false
16
+    isTier = false
16
     mySignup
17
     mySignup
17
 
18
 
18
     raid: RaidData = <any>{
19
     raid: RaidData = <any>{

+ 7
- 4
src/frontend/src/app/frontcraft/pages/raid/raid.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
-                <h1>{{raid.title}}</h1>
5
+                <h1>          
6
+                    <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" style="height: 100px" />
7
+                    {{raid.title}}
8
+                </h1>
6
                 <p>
9
                 <p>
7
                     {{raid.signupcount}} / {{raid.size}} signups
10
                     {{raid.signupcount}} / {{raid.size}} signups
8
                 </p>
11
                 </p>
167
                     </ng-container>
170
                     </ng-container>
168
                 </div>
171
                 </div>
169
             </nb-tab>
172
             </nb-tab>
170
-            <nb-tab tabTitle="Shop" *ngIf="isSignedup">
171
-                <shop (onSelect)="itemSelect($event)"></shop>
173
+            <nb-tab tabTitle="Items" *ngIf="isSignedup && isTier">
174
+                <shop [tier]="raid.tier" (onSelect)="itemSelect($event)"></shop>
172
             </nb-tab>
175
             </nb-tab>
173
-            <nb-tab tabTitle="Reserves">
176
+            <nb-tab tabTitle="Reserves" *ngIf="isTier">
174
                 <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
177
                 <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
175
 
178
 
176
                 <nb-list>
179
                 <nb-list>

+ 10
- 6
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts View File

6
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
6
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
7
 import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
7
 import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
8
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
8
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
9
+import { allItems } from '../../../../../../backend/Types/Items';
9
 
10
 
10
 @Component({
11
 @Component({
11
   selector: 'raid',
12
   selector: 'raid',
16
     canSignup = false
17
     canSignup = false
17
     isSignedup = false
18
     isSignedup = false
18
     islate = false
19
     islate = false
20
+    isTier = false
19
     manageRaid
21
     manageRaid
20
     mySignup: (Signup & Character & Spec)
22
     mySignup: (Signup & Character & Spec)
21
 
23
 
33
       },
35
       },
34
       tanks: [],
36
       tanks: [],
35
       healers: [],
37
       healers: [],
36
-      tokens:{}
38
+      tokens:{},
39
+      tier: 'MC'
37
     }
40
     }
38
     tokens = {}
41
     tokens = {}
39
     displayedtokens = {}
42
     displayedtokens = {}
50
     }
53
     }
51
 
54
 
52
     async ngOnInit(){
55
     async ngOnInit(){
56
+      
53
       this.manageRaid = this.api.get('manageRaid')
57
       this.manageRaid = this.api.get('manageRaid')
54
       
58
       
55
       const signupFeature = this.api.get('signup')
59
       const signupFeature = this.api.get('signup')
63
       this.dialogService.open(FrontcraftBuyTokenComponent, {
67
       this.dialogService.open(FrontcraftBuyTokenComponent, {
64
         context: {
68
         context: {
65
           item: item,
69
           item: item,
66
-          signup: this.mySignup
70
+          signup: this.mySignup,
71
+          tier: this.raid.tier,
72
+          characterName: this.mySignup.charactername
67
         }
73
         }
68
       }).onClose.subscribe(() => this.refresh())
74
       }).onClose.subscribe(() => this.refresh())
69
     }
75
     }
112
       const signup = this.api.get('signup')
118
       const signup = this.api.get('signup')
113
       if(!signup) return
119
       if(!signup) return
114
 
120
 
115
-      console.log("setlate");
116
-      
117
-
118
       await signup.sign(auth.token.value, {
121
       await signup.sign(auth.token.value, {
119
         ...this.mySignup,
122
         ...this.mySignup,
120
         id: this.mySignup.characterid,
123
         id: this.mySignup.characterid,
140
       const raiddata = await raidManager.getRaidData(<any>{
143
       const raiddata = await raidManager.getRaidData(<any>{
141
         id: param
144
         id: param
142
       })
145
       })
143
-        
146
+      this.isTier = allItems[raiddata.tier] != null
147
+
144
       this.raid = raiddata
148
       this.raid = raiddata
145
       this.tokens = raiddata.tokens;
149
       this.tokens = raiddata.tokens;
146
 
150
 

+ 4
- 0
src/frontend/src/app/frontcraft/pages/raids/createraid.component.html View File

7
     <nb-select [(selected)]="template" placeholder="copy from" (selectedChange)="onTemplateSelect()">
7
     <nb-select [(selected)]="template" placeholder="copy from" (selectedChange)="onTemplateSelect()">
8
         <nb-option *ngFor="let template of templates" [value]="template">{{template.title}} {{template.start| date : 'd MMMM'}}</nb-option>
8
         <nb-option *ngFor="let template of templates" [value]="template">{{template.title}} {{template.start| date : 'd MMMM'}}</nb-option>
9
     </nb-select>
9
     </nb-select>
10
+
11
+    <nb-select [(selected)]="tier" placeholder="Tier" >
12
+      <nb-option *ngFor="let _tier of tiers" [value]="_tier">{{_tier}}</nb-option>
13
+    </nb-select>
10
     
14
     
11
     <input type="text" nbInput [(ngModel)]="title" placeholder="Title" fullWidth="true">
15
     <input type="text" nbInput [(ngModel)]="title" placeholder="Title" fullWidth="true">
12
     <input type="number" nbInput [(ngModel)]="size" placeholder="size" fullWidth="true">
16
     <input type="number" nbInput [(ngModel)]="size" placeholder="size" fullWidth="true">

+ 5
- 0
src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts View File

2
 import { ApiService } from '../../services/login-api';
2
 import { ApiService } from '../../services/login-api';
3
 import { Raid, RaidData } from '../../../../../../backend/Types/Types';
3
 import { Raid, RaidData } from '../../../../../../backend/Types/Types';
4
 import { NbWindowRef, NbDialogRef } from '@nebular/theme';
4
 import { NbWindowRef, NbDialogRef } from '@nebular/theme';
5
+import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
5
 
6
 
6
 const ONE_MINUTE = 60000
7
 const ONE_MINUTE = 60000
7
 const ONE_HOUR = 60 * ONE_MINUTE
8
 const ONE_HOUR = 60 * ONE_MINUTE
21
   minute = 0
22
   minute = 0
22
   size = 40
23
   size = 40
23
   description = ""
24
   description = ""
25
+  tier: Tiers = null 
26
+  tiers = _Tiers
24
 
27
 
25
   constructor(
28
   constructor(
26
     protected dialogRef: NbDialogRef<FrontcraftCreateRaidsComponent>,
29
     protected dialogRef: NbDialogRef<FrontcraftCreateRaidsComponent>,
37
     this.minute = templateDate.getMinutes()
40
     this.minute = templateDate.getMinutes()
38
     this.description = this.template.description
41
     this.description = this.template.description
39
     this.startdate = new Date(parseInt(this.template.start) - templateDate.getHours()*ONE_HOUR - templateDate.getMinutes()*ONE_MINUTE)
42
     this.startdate = new Date(parseInt(this.template.start) - templateDate.getHours()*ONE_HOUR - templateDate.getMinutes()*ONE_MINUTE)
43
+    this.tier = this.template.tier
40
   }
44
   }
41
 
45
 
42
   ngOnInit(){
46
   ngOnInit(){
49
       size: this.size,
53
       size: this.size,
50
       start: ""+new Date(this.startdate.getTime() + this.hour*ONE_HOUR + this.minute*ONE_MINUTE).getTime(),
54
       start: ""+new Date(this.startdate.getTime() + this.hour*ONE_HOUR + this.minute*ONE_MINUTE).getTime(),
51
       title: this.title,
55
       title: this.title,
56
+      tier: this.tier
52
     }
57
     }
53
     const manage = this.api.get('manageRaid')
58
     const manage = this.api.get('manageRaid')
54
     if(!manage) return
59
     if(!manage) return

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

17
     style="cursor: pointer;">
17
     style="cursor: pointer;">
18
       <div class="row">
18
       <div class="row">
19
         <div class="col-2">
19
         <div class="col-2">
20
-          <img src="../../../../assets/images/mage.png" style="height: 75px" />
20
+          <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" style="height: 75px" />
21
         </div>
21
         </div>
22
 
22
 
23
         <div class="col-2 vcenter">
23
         <div class="col-2 vcenter">

+ 1
- 9
src/frontend/src/app/frontcraft/pages/rules/rules.component.html View File

7
             <nb-tab tabTitle="priorities">
7
             <nb-tab tabTitle="priorities">
8
                 <nb-list>
8
                 <nb-list>
9
                     <nb-list-item *ngFor="let item of rules | keyvalue">
9
                     <nb-list-item *ngFor="let item of rules | keyvalue">
10
-                        <a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}" 
11
-                        target="_blank" 
12
-                        [href]="item.value[0].url">
13
-                        <img style="min-width: 25px; width: 2.25vw; max-width: 50px" 
14
-                        [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.value[0].iconname+'.jpg'" />
15
-                        &nbsp;
16
-                        {{item.key}}
17
-                        </a><br />
18
-
10
+                        <wowhead [item]="item.value[0]"></wowhead><br>
19
                         <span *ngFor="let rule of item.value" [nbPopover]="templateRef" nbPopoverTrigger="hover">
11
                         <span *ngFor="let rule of item.value" [nbPopover]="templateRef" nbPopoverTrigger="hover">
20
                             <ng-template #templateRef>
12
                             <ng-template #templateRef>
21
                                 <span style="color:white">{{rule.description}}</span>
13
                                 <span style="color:white">{{rule.description}}</span>

+ 69
- 47
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts View File

15
       </nb-card-header>
15
       </nb-card-header>
16
       <nb-card-body>
16
       <nb-card-body>
17
         <p>
17
         <p>
18
-          You currently have {{currency}} softreserve currency
18
+          {{currency}} softreserves remaining
19
         </p>  
19
         </p>  
20
         <div *ngIf="currency>0">
20
         <div *ngIf="currency>0">
21
-          <div *ngFor="let kv of modifier | keyvalue">
22
-            <button
23
-                (click)="buyToken(kv.key)"
24
-                [disabled]="currency<=0"
25
-                nbButton 
26
-                outline 
27
-                status="success" 
28
-                size="tiny">
29
-                buy
30
-            </button>
31
-            {{kv.key}} <span *ngIf="kv.value>0">(<b>+{{kv.value}}</b> from priorities)</span>
32
-          </div>
33
-          <div *ngFor="let token of ownedtokens">
21
+            <nb-alert accent="danger" *ngIf="invalidatedTokens.length > 0">
22
+                Claiming this reserve invalidates the following streaks. <br />
23
+                This is not reversible.
24
+                <ul *ngFor="let item of invalidatedTokens">
25
+                    <li>
26
+                        [ {{item.level}} ] 
27
+                        <img style="min-width: 20px; width: 2.25vw; max-width: 35px" [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.iconname+'.jpg'" />
28
+                        <span [ngStyle]="{'color':item.quality=='Epic'?'#a335ee':'#ff8000'}">
29
+                            {{item.itemname}}
30
+                        </span>
31
+                    </li>
32
+                </ul>
33
+            </nb-alert>
34
+            
35
+            <nb-alert accent="info" *ngIf="noToken">  
36
+                The following reserve will be created<br />
37
+                <ul>
38
+                    <li>
39
+                        [ {{1+modifier}} ] 
40
+                        <img style="min-width: 20px; width: 2.25vw; max-width: 35px" [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.iconname+'.jpg'" />
41
+                        <span [ngStyle]="{'color':item.quality=='Epic'?'#a335ee':'#ff8000'}">
42
+                        {{item.itemname}}
43
+                        </span>
44
+                        <span *ngIf="modifier>0">(<b>+{{modifier}}</b> from priorities)</span>
45
+                    </li>
46
+                </ul>
47
+              
48
+            </nb-alert>
49
+
50
+            <nb-alert accent="info" *ngIf="upgradableToken != null">
51
+                The following reserve will be created<br />
52
+                <ul>
53
+                    <li>
54
+                        [ {{upgradableToken.level}} ] => [ {{upgradableToken.level+1}} ] <img style="min-width: 20px; width: 2.25vw; max-width: 35px" [src]="'https://wow.zamimg.com/images/wow/icons/large/'+upgradableToken.iconname+'.jpg'" />
55
+                        <span [ngStyle]="{'color':upgradableToken.quality=='Epic'?'#a335ee':'#ff8000'}">{{upgradableToken.itemname}}</span>
56
+                    </li>
57
+                </ul>
58
+              </nb-alert>
59
+            </div>
34
             <button
60
             <button
35
-                (click)="buyToken(token.charactername)"
36
-                nbButton 
37
-                outline 
38
-                status="success" 
39
-                size="tiny">
40
-                buy
61
+                  (click)="buyToken()"
62
+                  [disabled]="currency<=0"
63
+                  nbButton 
64
+                  outline 
65
+                  status="success" 
66
+                  size="small">
67
+                  <nb-icon icon="checkmark-outline"></nb-icon> claim
41
             </button>
68
             </button>
42
-            {{token.charactername}} [ {{token.level}} ] => [ {{token.level+1}} ]
43
-          </div>
44
-        </div>
45
       </nb-card-body>
69
       </nb-card-body>
46
   </nb-card>
70
   </nb-card>
47
     
71
     
48
     `,
72
     `,
49
   })
73
   })
50
   export class FrontcraftBuyTokenComponent implements OnInit{
74
   export class FrontcraftBuyTokenComponent implements OnInit{
51
-  
75
+    @Input() characterName: string
52
     @Input() item : Item
76
     @Input() item : Item
53
     @Input() signup : Signup
77
     @Input() signup : Signup
54
-
55
     @Input() tier: Tiers
78
     @Input() tier: Tiers
56
 
79
 
57
-    characters: Character[]
58
-    modifier = {}
80
+    invalidatedTokens: (SRToken & Character & Item)[] | undefined = []
81
+    upgradableToken : (SRToken & Character & Item) | undefined
82
+    noToken = false
83
+    modifier
59
     currency: number = 0
84
     currency: number = 0
60
-    ownedtokens: SRToken[] = []
61
   
85
   
62
     constructor(
86
     constructor(
63
       private toastr: NbToastrService,
87
       private toastr: NbToastrService,
65
       private api : ApiService
89
       private api : ApiService
66
     ){}
90
     ){}
67
   
91
   
68
-    ngOnInit(): void {
92
+    async ngOnInit() {
93
+        const char = await this.api.get('CharacterManager').getCharacterByName(this.characterName)
94
+        if(!char) return
95
+
96
+        const passiveStreaks = await this.api.get('ItemManager').getTokens(char, [this.item.tier], false)
97
+        this.upgradableToken = passiveStreaks.find(p => p.itemname === this.item.itemname)
98
+        this.invalidatedTokens = passiveStreaks.filter(token => token.itemname !== this.item.itemname)
99
+        if(!this.upgradableToken)                
100
+            this.upgradableToken = await this.api.get('ItemManager').getToken(char, this.item, true)                
101
+        this.modifier = await this.api.get('ItemManager').calculatePriorities(this.item.itemname, char)
102
+
103
+        if(!this.upgradableToken) this.noToken = true
104
+
69
         const usr = this.api.getCurrentUser()
105
         const usr = this.api.getCurrentUser()
70
         this.api.get('CharacterManager')
106
         this.api.get('CharacterManager')
71
         .getCharactersOfUser(usr.username)
107
         .getCharactersOfUser(usr.username)
72
         .then(chars => {
108
         .then(chars => {
73
-            chars.forEach(char => {
109
+            chars.forEach(async char => {
74
                 char['color'] = getClassColor(char.class)
110
                 char['color'] = getClassColor(char.class)
75
-                this.api.get('ItemManager').getToken(char, this.item, false).then(token => {
76
-                    if(token) this.ownedtokens.push(token)
77
-                    else{
78
-                        this.api.get('ItemManager').getToken(char, this.item, true).then(tokken => {
79
-                            if(tokken) this.ownedtokens.push(tokken)
80
-                            else{
81
-                                this.api.get('ItemManager').calculatePriorities(this.item.itemname, char).then(modifier => {
82
-                                    this.modifier[char.charactername] = modifier
83
-                                })
84
-                            }
85
-                        })
86
-                    }
87
-                })
88
             })
111
             })
89
-            this.characters = chars
90
         })
112
         })
91
         this.api.get('UserManager').getUser(usr.username).then(u => {
113
         this.api.get('UserManager').getUser(usr.username).then(u => {
92
           if(!u) return
114
           if(!u) return
93
-          this.currency = u.currency
115
+          this.currency = u[this.tier] || 0
94
         })
116
         })
95
     }
117
     }
96
   
118
   
97
-    buyToken = async (charactername:string) => {
119
+    buyToken = async () => {
98
         const src = this.api.get('ItemManager')
120
         const src = this.api.get('ItemManager')
99
-        const token = await src.buyToken(this.api.getAuth().token.value, charactername, this.item.itemname, this.signup)
121
+        const token = await src.buyToken(this.api.getAuth().token.value, this.characterName, this.item.itemname, this.signup)
100
     
122
     
101
         if(token){
123
         if(token){
102
         this.toastr.show(token.charactername+' now has a token for '+token.itemname+' of level '+token.level, 'Yay', {status: 'success'})
124
         this.toastr.show(token.charactername+' now has a token for '+token.itemname+' of level '+token.level, 'Yay', {status: 'success'})

+ 30
- 0
src/frontend/src/app/frontcraft/pages/shop/item.component.ts View File

1
+import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
2
+import { ApiService as ApiService } from '../../services/login-api';
3
+import { FrontcraftItemSelectComponent } from './itemselector.component';
4
+import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
5
+import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
6
+import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
+import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
8
+
9
+@Component({
10
+    selector: 'item',
11
+    template: `
12
+        <span [ngStyle]="{'color':item.quality=='Epic'?'#a335ee':'#ff8000'}">
13
+            <img style="min-width: 20px; width: 2.25vw; max-width: 35px" 
14
+            [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.iconname+'.jpg'" />
15
+            &nbsp;
16
+            {{item.itemname}}
17
+        </span>
18
+    `,
19
+  })
20
+  export class FrontcraftItemComponent implements OnInit{
21
+    @Input() item: Item
22
+  
23
+    constructor(
24
+      private toastr: NbToastrService,
25
+      private api : ApiService
26
+    ){}
27
+  
28
+    async ngOnInit() {
29
+    }
30
+  }

+ 2
- 8
src/frontend/src/app/frontcraft/pages/shop/itemselect.component.html View File

14
                 select
14
                 select
15
             </button>
15
             </button>
16
             &nbsp;
16
             &nbsp;
17
-            <a target="_blank" [href]="item.url">
18
-                <span [ngStyle]="{'color':item.quality=='Epic'?'#a335ee':'#ff8000'}">
19
-                    <img style="min-width: 20px; width: 2.25vw; max-width: 35px" 
20
-                    [src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.iconname+'.jpg'" />
21
-                    &nbsp;
22
-                    {{item.itemname}}
23
-                </span>
24
-            </a>
17
+                <wowhead [item]="item"></wowhead>
18
+                
25
         </nb-list-item>
19
         </nb-list-item>
26
     </nb-list>
20
     </nb-list>

+ 3
- 1
src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts View File

1
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
1
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2
 import { ApiService } from '../../services/login-api';
2
 import { ApiService } from '../../services/login-api';
3
-import { Item } from '../../../../../../backend/Types/Types';
3
+import { Item, Character } from '../../../../../../backend/Types/Types';
4
 
4
 
5
 @Component({
5
 @Component({
6
   selector: 'itemselect',
6
   selector: 'itemselect',
13
     allItems:Item[] = []
13
     allItems:Item[] = []
14
     displayedItems: any[]
14
     displayedItems: any[]
15
 
15
 
16
+    @Input() character: string
16
     @Input() items: string[]
17
     @Input() items: string[]
17
     @Output() onSelect = new EventEmitter<Item>();
18
     @Output() onSelect = new EventEmitter<Item>();
18
 
19
 
21
     ){}
22
     ){}
22
 
23
 
23
     async ngOnInit(){
24
     async ngOnInit(){
25
+        
24
         Promise.all(this.items.map(itemname => 
26
         Promise.all(this.items.map(itemname => 
25
             this.api.get('ItemManager').getItem(itemname)
27
             this.api.get('ItemManager').getItem(itemname)
26
         )).then(items => {
28
         )).then(items => {

+ 4
- 6
src/frontend/src/app/frontcraft/pages/shop/shop.component.html View File

1
-<h3>
2
-    {{tier}} items
3
-</h3>
4
-
5
-<itemselect             
1
+<itemselect
2
+[character]="character"          
6
 [items]="allItems[tier]"
3
 [items]="allItems[tier]"
7
-(onSelect)="onSelect.emit($event)"></itemselect>
4
+(onSelect)="onSelect.emit($event)"></itemselect
5
+>

+ 7
- 2
src/frontend/src/app/frontcraft/pages/shop/shop.component.ts View File

10
   selector: 'shop',
10
   selector: 'shop',
11
   templateUrl: './shop.component.html',
11
   templateUrl: './shop.component.html',
12
 })
12
 })
13
-export class FrontcraftShopComponent{
13
+export class FrontcraftShopComponent implements OnInit{
14
 
14
 
15
     @Input() character: Character
15
     @Input() character: Character
16
     @Input() signup: Signup
16
     @Input() signup: Signup
22
     constructor(
22
     constructor(
23
       private api: ApiService,
23
       private api: ApiService,
24
       private dialogService : NbDialogService
24
       private dialogService : NbDialogService
25
-    ){}
25
+    ){
26
+
27
+    }
28
+
29
+    ngOnInit(){
30
+    }
26
 }
31
 }

+ 26
- 0
src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts View File

1
+import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
2
+import { ApiService as ApiService } from '../../services/login-api';
3
+import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
4
+import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
5
+import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
6
+
7
+@Component({
8
+    selector: 'wowhead',
9
+    template: `
10
+    <a target="_blank" [href]="item.url">
11
+        <item [item]="item"></item>
12
+    </a>
13
+    
14
+    `,
15
+  })
16
+  export class FrontcraftWowheadComponent implements OnInit{
17
+    @Input() item: Item
18
+  
19
+    constructor(
20
+      private toastr: NbToastrService,
21
+      private api : ApiService
22
+    ){}
23
+  
24
+    async ngOnInit() {
25
+    }
26
+  }

+ 6
- 1
src/frontend/src/app/frontcraft/pages/user/user.component.html View File

6
         <h2 style="text-transform: capitalize;">{{user.username}}</h2>
6
         <h2 style="text-transform: capitalize;">{{user.username}}</h2>
7
     </nb-card-header>
7
     </nb-card-header>
8
     <nb-card-body>
8
     <nb-card-body>
9
-        {{user.currency}}
9
+        {{user.MC}} MC
10
+        {{user.BWL}} BWL
11
+        {{user.ZG}} ZG
12
+        {{user.AQ20}} AQ20
13
+        {{user.AQ40}} AQ40
14
+        {{user.Naxx}} Naxx
10
       <ng-container *ngFor="let char of characters">
15
       <ng-container *ngFor="let char of characters">
11
           <character [name]="char.charactername" [link]="'character'"></character>
16
           <character [name]="char.charactername" [link]="'character'"></character>
12
       </ng-container>
17
       </ng-container>

+ 2
- 1
src/frontend/src/app/frontcraft/pages/user/user.component.ts View File

3
 import { Router, ActivatedRoute } from '@angular/router';
3
 import { Router, ActivatedRoute } from '@angular/router';
4
 import { User, Spec, Character } from '../../../../../../backend/Types/Types';
4
 import { User, Spec, Character } from '../../../../../../backend/Types/Types';
5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
+import { _Tiers } from '../../../../../../backend/Types/Items';
6
 
7
 
7
 @Component({
8
 @Component({
8
   selector: 'user-component',
9
   selector: 'user-component',
28
 
29
 
29
     const characters = await this.api.get('CharacterManager').getCharactersOfUser(this.user.username)
30
     const characters = await this.api.get('CharacterManager').getCharactersOfUser(this.user.username)
30
     characters.forEach(async c => {
31
     characters.forEach(async c => {
31
-      const tokens = await this.api.get('ItemManager').getTokens(c)
32
+      const tokens = await this.api.get('ItemManager').getTokens(c, _Tiers, true)
32
       c['tokens'] = tokens
33
       c['tokens'] = tokens
33
       c['color'] = getClassColor(c.class)
34
       c['color'] = getClassColor(c.class)
34
     })
35
     })

BIN
src/frontend/src/assets/images/aq20.png View File


BIN
src/frontend/src/assets/images/aq40.png View File


BIN
src/frontend/src/assets/images/bwl.png View File


BIN
src/frontend/src/assets/images/mc.png View File


BIN
src/frontend/src/assets/images/naxx.png View File


BIN
src/frontend/src/assets/images/null.png View File


BIN
src/frontend/src/assets/images/ony.png View File


BIN
src/frontend/src/assets/images/zg.png View File


+ 21
- 10
test/backendTest.ts View File

60
         race: 'Night Elf',
60
         race: 'Night Elf',
61
         spec: 'Protection',
61
         spec: 'Protection',
62
         rank: 'Officer'
62
         rank: 'Officer'
63
+    },{
64
+        name: 'Silver',
65
+        class: 'Druid',
66
+        race: 'Night Elf',
67
+        spec: 'Restoration',
68
+        rank: 'Raider'
63
     },{
69
     },{
64
         name: 'Dagger',
70
         name: 'Dagger',
65
         race: 'Dwarf',
71
         race: 'Dwarf',
117
         const account = await createAccount({
123
         const account = await createAccount({
118
             pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
124
             pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
119
             rank: acc.rank,
125
             rank: acc.rank,
120
-            username: acc.name
126
+            username: acc.name,
121
         })
127
         })
122
         const auth = await client.UserManager.login(acc.name, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb')
128
         const auth = await client.UserManager.login(acc.name, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb')
123
         const id = await client.CharacterManager.getSpecId(acc.class, acc.spec)
129
         const id = await client.CharacterManager.getSpecId(acc.class, acc.spec)
148
                     pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //hash("a")
154
                     pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //hash("a")
149
                     rank: 'ADMIN',
155
                     rank: 'ADMIN',
150
                     username: 'a',
156
                     username: 'a',
151
-                    currency: 2
157
+                    MC: 2
152
                 }).then(adminUser => {
158
                 }).then(adminUser => {
153
 
159
 
154
                     client.UserManager.login(adminUser.username, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb').then(auth => {
160
                     client.UserManager.login(adminUser.username, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb').then(auth => {
187
         let insertRaid = <Raid>{
193
         let insertRaid = <Raid>{
188
             description: "Test raid 1",
194
             description: "Test raid 1",
189
             title: 'MC',
195
             title: 'MC',
190
-            start: Date.now().toString()
196
+            start: Date.now().toString(),
197
+            tier: 'MC'
191
         }
198
         }
192
 
199
 
193
         adminClient.manageRaid.createRaid(insertRaid).then(() => {
200
         adminClient.manageRaid.createRaid(insertRaid).then(() => {
391
                 {class:'Paladin', specname:'Holy'}, 
398
                 {class:'Paladin', specname:'Holy'}, 
392
                 undefined, 2, "crit bias"
399
                 undefined, 2, "crit bias"
393
             ),
400
             ),
401
+            makePrio(
402
+                'Empowered Leggings', 
403
+                {class:'Druid', specname:'Restoration'}, 
404
+                undefined, 2, "crit bias"
405
+            ),
394
 
406
 
395
             makePrio(
407
             makePrio(
396
                 'Boots of the Shadow Flame', 
408
                 'Boots of the Shadow Flame', 
516
         const user = Object.values(users)[0]
528
         const user = Object.values(users)[0]
517
         const itemname = T1[0]
529
         const itemname = T1[0]
518
 
530
 
519
-        adminClient.softreserveCurrency.incrementCurrency(user.account, 2).then(async ()=>{
531
+        adminClient.softreserveCurrency.incrementCurrency(user.account, raids[0].tier, 2).then(async ()=>{
520
             const item = await client.ItemManager.getItem(itemname)
532
             const item = await client.ItemManager.getItem(itemname)
521
             const before = await client.ItemManager.getToken(user.character, item)
533
             const before = await client.ItemManager.getToken(user.character, item)
522
             
534
             
538
 
550
 
539
     it('should buy more tokens', (done) => {
551
     it('should buy more tokens', (done) => {
540
         Promise.all(Object.values(users).map(async (user) => {
552
         Promise.all(Object.values(users).map(async (user) => {
541
-            await adminClient.softreserveCurrency.incrementCurrency(user.account, 1)
553
+            await adminClient.softreserveCurrency.incrementCurrency(user.account,raids[0].tier, 1)
542
             return await client.ItemManager
554
             return await client.ItemManager
543
             .buyToken(
555
             .buyToken(
544
                 user.auth.token.value, 
556
                 user.auth.token.value, 
565
                 const dbRaids = await client.RaidManager.getRaids()
577
                 const dbRaids = await client.RaidManager.getRaids()
566
                 if(dbRaids.length === 0){
578
                 if(dbRaids.length === 0){
567
                     await client.UserManager.getUser(testAccounts[0].name).then(dbUser => {
579
                     await client.UserManager.getUser(testAccounts[0].name).then(dbUser => {
568
-                        if(dbUser && dbUser.currency === 1){
580
+                        if(dbUser && dbUser.MC === 1){
569
                             adminClient.signup.getSignups(raids[0]).then(signups => {
581
                             adminClient.signup.getSignups(raids[0]).then(signups => {
570
                                 if(signups.length === 0){
582
                                 if(signups.length === 0){
571
                                     done()
583
                                     done()
586
     it('reset system', (done) => {
598
     it('reset system', (done) => {
587
         adminClient.reset.wipeCurrencyAndItems().then(() => {
599
         adminClient.reset.wipeCurrencyAndItems().then(() => {
588
             client.UserManager.getUser(testAccounts[0].name).then(user => {
600
             client.UserManager.getUser(testAccounts[0].name).then(user => {
589
-                if(user && user.currency === 0){
590
-                    client.ItemManager.getTokens(users[testAccounts[0].name.toLowerCase()].character).then(tokens => {
591
-                        if(tokens.length === 0){
601
+                if(user && user.MC === 1){
602
+                    client.ItemManager.getTokens(users[testAccounts[0].name.toLowerCase()].character, ['MC']).then(tokens => {
603
+                        if(tokens!.length === 0){
592
                             done()
604
                             done()
593
                         }else{
605
                         }else{
594
                             console.log(tokens);
606
                             console.log(tokens);
599
                 }
611
                 }
600
             })
612
             })
601
         })
613
         })
602
-        
603
     })
614
     })
604
 })
615
 })

Loading…
Cancel
Save