浏览代码

working buytoken (untested)

master
peter 5 年前
父节点
当前提交
59f518679e
共有 37 个文件被更改,包括 345 次插入220 次删除
  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. 二进制
      src/frontend/src/assets/images/aq20.png
  30. 二进制
      src/frontend/src/assets/images/aq40.png
  31. 二进制
      src/frontend/src/assets/images/bwl.png
  32. 二进制
      src/frontend/src/assets/images/mc.png
  33. 二进制
      src/frontend/src/assets/images/naxx.png
  34. 二进制
      src/frontend/src/assets/images/null.png
  35. 二进制
      src/frontend/src/assets/images/ony.png
  36. 二进制
      src/frontend/src/assets/images/zg.png
  37. 21
    10
      test/backendTest.ts

+ 3
- 2
package.json 查看文件

@@ -4,9 +4,10 @@
4 4
   "version": "1.0.0",
5 5
   "scripts": {
6 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 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 11
     "test": "npm run clean && npm run build-backend && mocha lib/test/backendTest.js",
11 12
     "build-backend": "tsc;",
12 13
     "build-frontend": "mkdir dist; mkdir dist/static; npm run build-dashboard;",

+ 4
- 3
src/backend/Components/Item/Interface.ts 查看文件

@@ -1,14 +1,15 @@
1 1
 import { Item, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types"
2
+import { Tiers } from "../../Types/Items"
2 3
 
3 4
 export class IItemManager{
4 5
     getItems: () => Promise<Item[]>
5 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 8
     setPriority: (itemname:string, priority: any) => Promise<void>
8 9
     calculatePriorities: (itemname: string, character:Character) => Promise<number>
9 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 13
     getAllPriorities: () => Promise<(SRPriority & Spec & Item)[]>
13 14
     wipeCurrencyAndItems: () => Promise<void>
14 15
 }

+ 66
- 59
src/backend/Components/Item/ItemManager.ts 查看文件

@@ -1,4 +1,4 @@
1
-import { T1, T2, allItems, _Tiers } from "../../Types/Items";
1
+import { T1, T2, allItems, _Tiers, Tiers } from "../../Types/Items";
2 2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
3 3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
4 4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
@@ -54,7 +54,7 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
54 54
     wipeCurrencyAndItems = async () => {
55 55
         await Promise.all([
56 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,19 +84,21 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
84 84
 
85 85
     getTableDefinitions(): TableDefiniton[] {
86 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 102
                 name: 'priorities',
101 103
                 tableBuilder: (table) => {
102 104
                     table.increments('id').primary()
@@ -121,7 +123,7 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
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 127
         const record = this.userManager.getUserRecordByToken(usertoken)
126 128
         const character = await this.character.getCharacterByName(charactername)
127 129
 
@@ -130,52 +132,53 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
130 132
         const item = await this.getItem(itemname)
131 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 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 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 149
                 await this.admin
152
-                .knex('tokens')
150
+                .knex(item.tier+'tokens')
153 151
                 .where({
154 152
                     characterid: character.id,
155 153
                     itemname: item.itemname
156 154
                 })
157 155
                 .update({
158 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 165
                 .where({
166
+                    itemname: s.itemname,
165 167
                     characterid: character.id,
166
-                    itemname: item.itemname,
167 168
                     signupid: null
168
-                }).del()
169
-                
169
+                })
170
+                .del()
171
+            ))
172
+            
173
+            if(myStreak)
170 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 180
             await this.admin
178
-            .knex('tokens')
181
+            .knex(item.tier+'tokens')
179 182
             .increment('level')
180 183
             .where({
181 184
                 signupid: signup.id,
@@ -183,8 +186,9 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
183 186
                 itemname: item.itemname
184 187
             })
185 188
         }else{
189
+            getLogger('ItemManager').debug('new reserve')
186 190
             await this.admin
187
-            .knex('tokens')
191
+            .knex(item.tier+'tokens')
188 192
             .insert({
189 193
                 characterid: character.id,
190 194
                 itemname: item.itemname,
@@ -257,9 +261,9 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
257 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 265
         return await this.admin
262
-        .knex('tokens as t')
266
+        .knex(item.tier+'tokens as t')
263 267
         .select('*')
264 268
         .join('characters as c', 'c.id', '=', 't.characterid')
265 269
         .join('items as i', 'i.itemname', '=', 't.itemname')
@@ -277,22 +281,25 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
277 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 305
     countItems = async() :Promise<number> => {

+ 28
- 28
src/backend/Components/Raid/RaidManager.ts 查看文件

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

+ 5
- 4
src/backend/Components/User/Interface.ts 查看文件

@@ -1,4 +1,5 @@
1 1
 import { Auth, Rank, User, RPCPermission, UserRecord } from "../../Types/Types"
2
+import { Tiers } from "../../Types/Items"
2 3
 
3 4
 export class IUserManager{
4 5
     login: (username:string, pwHash:string) => Promise<Auth>
@@ -11,10 +12,10 @@ export class IUserManager{
11 12
     getUserRecordByToken: (tokenValue: string) => UserRecord | void
12 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 19
     changeRank: (user:User, rank: Rank) => Promise<User>
19 20
     wipeCurrency: () => Promise<void>
20 21
 }

+ 24
- 16
src/backend/Components/User/UserManager.ts 查看文件

@@ -12,6 +12,7 @@ import { IAdmin } from "../../Admin/Interface";
12 12
 import { IUserManager } from "./Interface";
13 13
 import { getLogger, Logger } from "log4js";
14 14
 import { saltedHash } from "../../Util/hash";
15
+import { _Tiers, Tiers } from "../../Types/Items";
15 16
 
16 17
 const uuid = require('uuid/v4')
17 18
 
@@ -97,8 +98,9 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
97 98
                 table.string("username").notNullable().unique()
98 99
                 table.string("pwhash").notNullable()
99 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 106
             name: 'rpcpermissions',
@@ -286,8 +288,13 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
286 288
     }
287 289
 
288 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 300
     login = async(username:string, pwHash:string) : Promise<Auth> => {
@@ -405,18 +412,19 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
405 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 417
         const usr : User = await this.admin
410 418
         .knex('users')
411 419
         .where('username', '=', user.username)
412 420
         .select('*')
413 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 429
         const usr : User = await this.admin
422 430
         .knex('users')
@@ -424,28 +432,28 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
424 432
         .select('*')
425 433
         .first()
426 434
 
427
-        if(!usr || usr.currency! <= 0) return
435
+        if(!usr || usr[tier]! <= 0) return
428 436
 
429 437
         await this.admin
430 438
         .knex('users')
431 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 445
         await this.admin
438 446
         .knex('users')
439 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 453
         await this.admin
446 454
         .knex('users')
447 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 查看文件

@@ -1,5 +1,5 @@
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 4
 export const T1 = [
5 5
 "Robe of Volatile Power",

+ 2
- 0
src/backend/Types/Types.ts 查看文件

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

+ 5
- 2
src/frontend/src/app/@theme/components/header/chat.component.ts 查看文件

@@ -10,9 +10,12 @@ import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Inte
10 10
                            [type]="text"
11 11
                            [message]="msg.message"
12 12
                            [sender]="msg.sender"
13
-                           [date]="msg.date">
13
+                           [date]="msg.date"
14
+                           [reply]="msg.reply">
14 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 19
           </nb-chat-form>
17 20
         </nb-chat>
18 21
   `, 

+ 1
- 7
src/frontend/src/app/frontcraft/pages/character/character.component.html 查看文件

@@ -25,13 +25,7 @@ status="control">
25 25
         <br/><br />
26 26
         <span *ngFor="let token of tokens">
27 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 29
         </span>
36 30
     </nb-card-body>
37 31
 </nb-card>

+ 2
- 1
src/frontend/src/app/frontcraft/pages/character/character.component.ts 查看文件

@@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
3 3
 import { ApiService as ApiService } from '../../services/login-api';
4 4
 import { Spec, User, Character } from '../../../../../../backend/Types/Types';
5 5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
+import { _Tiers } from '../../../../../../backend/Types/Items';
6 7
 
7 8
 @Component({
8 9
   selector: 'character',
@@ -35,7 +36,7 @@ export class FrontcraftCharacterComponent implements OnInit{
35 36
         if(char){
36 37
           this.color = getClassColor(char.class)
37 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 40
             this.tokens = tokens
40 41
           })
41 42
         }

+ 4
- 0
src/frontend/src/app/frontcraft/pages/pages.module.ts 查看文件

@@ -38,6 +38,8 @@ import { FrontcraftItemSelectComponent } from './shop/itemselector.component';
38 38
 import { NgxEchartsModule } from 'ngx-echarts';
39 39
 import { FrontcraftCharactersComponent } from './characters/characters.component';
40 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 45
 @NgModule({
@@ -81,6 +83,8 @@ import { FrontcraftBuyTokenComponent } from './shop/buytoken.component';
81 83
     FrontcraftRulesComponent,
82 84
     FrontcraftCreateRaidsComponent,
83 85
     FrontcraftBuyTokenComponent,
86
+    FrontcraftWowheadComponent,
87
+    FrontcraftItemComponent
84 88
   ],
85 89
   entryComponents: [
86 90
     FrontcraftItemSelectComponent,

+ 1
- 0
src/frontend/src/app/frontcraft/pages/raid/archive.component.ts 查看文件

@@ -13,6 +13,7 @@ export class FrontcraftArchiveComponent implements OnInit{
13 13
     canSignup = false
14 14
     isSignedup = false
15 15
     canManage = false
16
+    isTier = false
16 17
     mySignup
17 18
 
18 19
     raid: RaidData = <any>{

+ 7
- 4
src/frontend/src/app/frontcraft/pages/raid/raid.component.html 查看文件

@@ -2,7 +2,10 @@
2 2
     <nb-card-body>
3 3
         <nb-tabset>
4 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 9
                 <p>
7 10
                     {{raid.signupcount}} / {{raid.size}} signups
8 11
                 </p>
@@ -167,10 +170,10 @@
167 170
                     </ng-container>
168 171
                 </div>
169 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 175
             </nb-tab>
173
-            <nb-tab tabTitle="Reserves">
176
+            <nb-tab tabTitle="Reserves" *ngIf="isTier">
174 177
                 <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
175 178
 
176 179
                 <nb-list>

+ 10
- 6
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts 查看文件

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

+ 4
- 0
src/frontend/src/app/frontcraft/pages/raids/createraid.component.html 查看文件

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

+ 5
- 0
src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts 查看文件

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

+ 1
- 1
src/frontend/src/app/frontcraft/pages/raids/raids.component.html 查看文件

@@ -17,7 +17,7 @@
17 17
     style="cursor: pointer;">
18 18
       <div class="row">
19 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 21
         </div>
22 22
 
23 23
         <div class="col-2 vcenter">

+ 1
- 9
src/frontend/src/app/frontcraft/pages/rules/rules.component.html 查看文件

@@ -7,15 +7,7 @@
7 7
             <nb-tab tabTitle="priorities">
8 8
                 <nb-list>
9 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 11
                         <span *ngFor="let rule of item.value" [nbPopover]="templateRef" nbPopoverTrigger="hover">
20 12
                             <ng-template #templateRef>
21 13
                                 <span style="color:white">{{rule.description}}</span>

+ 69
- 47
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts 查看文件

@@ -15,49 +15,73 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
15 15
       </nb-card-header>
16 16
       <nb-card-body>
17 17
         <p>
18
-          You currently have {{currency}} softreserve currency
18
+          {{currency}} softreserves remaining
19 19
         </p>  
20 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 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 68
             </button>
42
-            {{token.charactername}} [ {{token.level}} ] => [ {{token.level+1}} ]
43
-          </div>
44
-        </div>
45 69
       </nb-card-body>
46 70
   </nb-card>
47 71
     
48 72
     `,
49 73
   })
50 74
   export class FrontcraftBuyTokenComponent implements OnInit{
51
-  
75
+    @Input() characterName: string
52 76
     @Input() item : Item
53 77
     @Input() signup : Signup
54
-
55 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 84
     currency: number = 0
60
-    ownedtokens: SRToken[] = []
61 85
   
62 86
     constructor(
63 87
       private toastr: NbToastrService,
@@ -65,38 +89,36 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
65 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 105
         const usr = this.api.getCurrentUser()
70 106
         this.api.get('CharacterManager')
71 107
         .getCharactersOfUser(usr.username)
72 108
         .then(chars => {
73
-            chars.forEach(char => {
109
+            chars.forEach(async char => {
74 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 113
         this.api.get('UserManager').getUser(usr.username).then(u => {
92 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 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 123
         if(token){
102 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 查看文件

@@ -0,0 +1,30 @@
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 查看文件

@@ -14,13 +14,7 @@
14 14
                 select
15 15
             </button>
16 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 19
         </nb-list-item>
26 20
     </nb-list>

+ 3
- 1
src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts 查看文件

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

+ 4
- 6
src/frontend/src/app/frontcraft/pages/shop/shop.component.html 查看文件

@@ -1,7 +1,5 @@
1
-<h3>
2
-    {{tier}} items
3
-</h3>
4
-
5
-<itemselect             
1
+<itemselect
2
+[character]="character"          
6 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 查看文件

@@ -10,7 +10,7 @@ import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
10 10
   selector: 'shop',
11 11
   templateUrl: './shop.component.html',
12 12
 })
13
-export class FrontcraftShopComponent{
13
+export class FrontcraftShopComponent implements OnInit{
14 14
 
15 15
     @Input() character: Character
16 16
     @Input() signup: Signup
@@ -22,5 +22,10 @@ export class FrontcraftShopComponent{
22 22
     constructor(
23 23
       private api: ApiService,
24 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 查看文件

@@ -0,0 +1,26 @@
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 查看文件

@@ -6,7 +6,12 @@ accent="info">
6 6
         <h2 style="text-transform: capitalize;">{{user.username}}</h2>
7 7
     </nb-card-header>
8 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 15
       <ng-container *ngFor="let char of characters">
11 16
           <character [name]="char.charactername" [link]="'character'"></character>
12 17
       </ng-container>

+ 2
- 1
src/frontend/src/app/frontcraft/pages/user/user.component.ts 查看文件

@@ -3,6 +3,7 @@ import { ApiService } from '../../services/login-api';
3 3
 import { Router, ActivatedRoute } from '@angular/router';
4 4
 import { User, Spec, Character } from '../../../../../../backend/Types/Types';
5 5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
+import { _Tiers } from '../../../../../../backend/Types/Items';
6 7
 
7 8
 @Component({
8 9
   selector: 'user-component',
@@ -28,7 +29,7 @@ export class FrontcraftUserComponent implements OnInit{
28 29
 
29 30
     const characters = await this.api.get('CharacterManager').getCharactersOfUser(this.user.username)
30 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 33
       c['tokens'] = tokens
33 34
       c['color'] = getClassColor(c.class)
34 35
     })

二进制
src/frontend/src/assets/images/aq20.png 查看文件


二进制
src/frontend/src/assets/images/aq40.png 查看文件


二进制
src/frontend/src/assets/images/bwl.png 查看文件


二进制
src/frontend/src/assets/images/mc.png 查看文件


二进制
src/frontend/src/assets/images/naxx.png 查看文件


二进制
src/frontend/src/assets/images/null.png 查看文件


二进制
src/frontend/src/assets/images/ony.png 查看文件


二进制
src/frontend/src/assets/images/zg.png 查看文件


+ 21
- 10
test/backendTest.ts 查看文件

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

正在加载...
取消
保存