Преглед на файлове

implement loot system feedback

master
peter преди 5 години
родител
ревизия
5ace7357a4
променени са 22 файла, в които са добавени 379 реда и са изтрити 196 реда
  1. 7
    0
      src/backend/Admin/Admin.ts
  2. 2
    2
      src/backend/Components/Item/Interface.ts
  3. 93
    46
      src/backend/Components/Item/ItemManager.ts
  4. 2
    2
      src/backend/Components/Raid/Interface.ts
  5. 47
    24
      src/backend/Components/Raid/RaidManager.ts
  6. 1
    2
      src/backend/Components/User/UserManager.ts
  7. 17
    1
      src/backend/Types/Items.ts
  8. 10
    6
      src/backend/Types/Types.ts
  9. 15
    3
      src/frontend/src/app/frontcraft/pages/character/character.component.html
  10. 7
    2
      src/frontend/src/app/frontcraft/pages/character/character.component.ts
  11. 0
    3
      src/frontend/src/app/frontcraft/pages/characters/characters.component.html
  12. 2
    1
      src/frontend/src/app/frontcraft/pages/pages.module.ts
  13. 3
    2
      src/frontend/src/app/frontcraft/pages/raid/raid.component.html
  14. 14
    3
      src/frontend/src/app/frontcraft/pages/raid/raid.component.ts
  15. 1
    1
      src/frontend/src/app/frontcraft/pages/rules/rules.component.html
  16. 104
    0
      src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts
  17. 12
    13
      src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts
  18. 6
    12
      src/frontend/src/app/frontcraft/pages/shop/shop.component.html
  19. 11
    26
      src/frontend/src/app/frontcraft/pages/shop/shop.component.ts
  20. 3
    27
      src/frontend/src/app/frontcraft/pages/user/user.component.html
  21. 0
    8
      src/frontend/src/app/frontcraft/services/login-api.ts
  22. 22
    12
      test/backendTest.ts

+ 7
- 0
src/backend/Admin/Admin.ts Целия файл

@@ -102,6 +102,13 @@ implements TableDefinitionExporter, IAdmin {
102 102
     private startWebsocket(){
103 103
         this.rpcServer = new RPCServer(20000, [
104 104
             ...this.frontworkComponents,
105
+            {
106
+                name: "debug",
107
+                exportRPCs: () => [{
108
+                    name: 'dumpDb',
109
+                    call: async (table) => await this.knex(table).select('*')
110
+                }]
111
+            }
105 112
         ], {
106 113
             visibility: '0.0.0.0'
107 114
         })

+ 2
- 2
src/backend/Components/Item/Interface.ts Целия файл

@@ -1,9 +1,9 @@
1
-import { Item, Character, SRToken, SRPriority, Spec } from "../../Types/Types"
1
+import { Item, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types"
2 2
 
3 3
 export class IItemManager{
4 4
     getItems: () => Promise<Item[]>
5 5
     fetchItem: (name:string) => Promise<Item>
6
-    buyToken: (usertoken: string, charactername:string, itemname:string) => Promise<(SRToken & Character & Item) | void>
6
+    buyToken: (usertoken: string, charactername:string, itemname:string, signup:Signup) => Promise<(SRToken & Character & Item) | void>
7 7
     setPriority: (itemname:string, priority: any) => Promise<void>
8 8
     calculatePriorities: (itemname: string, character:Character) => Promise<number>
9 9
     deletePriority: (priority:SRPriority) => Promise<void>

+ 93
- 46
src/backend/Components/Item/ItemManager.ts Целия файл

@@ -1,9 +1,9 @@
1
-import { T1, T2 } from "../../Types/Items";
1
+import { T1, T2, allItems, _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";
5 5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
6
-import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec } from "../../Types/Types";
6
+import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types";
7 7
 import { IAdmin } from "../../Admin/Interface";
8 8
 import { IItemManager } from "./Interface";
9 9
 import { getLogger } from "log4js";
@@ -87,19 +87,21 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
87 87
             {
88 88
                 name: 'tokens',
89 89
                 tableBuilder: (table) => {
90
-                    table.primary(['characterid', 'itemid'])
90
+                    table.primary(['characterid', 'itemname'])
91 91
                     table.integer("characterid")
92 92
                     table.foreign("characterid").references("id").inTable('characters')
93
-                    table.integer("itemid")
94
-                    table.foreign("itemid").references("id").inTable('items')
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')
95 97
                     table.integer("level").defaultTo(1)
96 98
                 }
97 99
             },{
98 100
                 name: 'priorities',
99 101
                 tableBuilder: (table) => {
100 102
                     table.increments('id').primary()
101
-                    table.integer('itemid')
102
-                    table.foreign('itemid').references('id').inTable('items')
103
+                    table.string('itemname')
104
+                    table.foreign('itemname').references('itemname').inTable('items')
103 105
                     table.string('race').nullable()
104 106
                     table.integer('specid').nullable()
105 107
                     table.foreign('specid').references('id').inTable('specs')
@@ -109,17 +111,17 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
109 111
             },{
110 112
                 name: 'items',
111 113
                 tableBuilder: (table) => {
112
-                    table.increments("id").primary()
113
-                    table.string('itemname').unique().notNullable()
114
+                    table.string('itemname').unique().notNullable().primary()
114 115
                     table.string('iconname').notNullable()
115 116
                     table.string('url').notNullable()
116 117
                     table.string('quality').defaultTo('Epic').notNullable()
117 118
                     table.boolean('hidden').defaultTo(false).notNullable()
119
+                    table.enu('tier', _Tiers).notNullable()
118 120
                 }
119 121
             }]
120 122
     }
121 123
 
122
-    buyToken = async (usertoken: string, charactername:string, itemname:string): Promise<(SRToken & Character & Item) | void> => {
124
+    buyToken = async (usertoken: string, charactername:string, itemname:string, signup: Signup): Promise<(SRToken & Character & Item) | void> => {
123 125
         const record = this.userManager.getUserRecordByToken(usertoken)
124 126
         const character = await this.character.getCharacterByName(charactername)
125 127
 
@@ -131,30 +133,62 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
131 133
         const currency = await this.userManager.getCurrency(record.user)
132 134
         if(currency < 1) return
133 135
 
134
-        const existingToken = await this.getToken(character, item)
136
+        const shadowTokens = await this.getTokens(character, false)
137
+        const activeTokens = await this.getTokens(character, true)
135 138
 
136 139
         await this.userManager.decrementCurrency(record.user, 1)
140
+        const modifier = await this.calculatePriorities(itemname, character)
137 141
 
138
-        if(!existingToken){
139
-            const modifier = await this.calculatePriorities(itemname, character)
140
-            await this.admin.knex('tokens').insert({
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
+                console.log("delete shadow tokens");
150
+
151
+                await this.admin
152
+                .knex('tokens')
153
+                .update({
154
+                    signupid: signup.id,
155
+                    level: matchingtoken.level+1
156
+                })
157
+                .where({
158
+                    characterid: character.id,
159
+                    itemname: item.itemname
160
+                })
161
+                return await this.getToken(character, item)
162
+            }
163
+        }
164
+
165
+        const matchingtoken = activeTokens.find(token => token.itemname === itemname)
166
+        if(matchingtoken){
167
+            //power up token
168
+            await this.admin
169
+            .knex('tokens')
170
+            .increment('level')
171
+            .where({
172
+                signupid: signup.id,
141 173
                 characterid: character.id,
142
-                itemid: item.id,
143
-                level: 1+modifier
174
+                itemname: item.itemname
144 175
             })
145 176
         }else{
146
-            await this.admin.knex('tokens').where({
177
+            await this.admin
178
+            .knex('tokens')
179
+            .insert({
147 180
                 characterid: character.id,
148
-                itemid: item.id
149
-            }).increment('level')
181
+                itemname: item.itemname,
182
+                level: 1+modifier,
183
+                signupid: signup.id
184
+            })
150 185
         }
151
-
152 186
         return await this.getToken(character, item)
153 187
     }
154 188
 
155 189
     getAllPriorities = async() :Promise<(SRPriority & Spec & Item)[]> => this.admin
156 190
     .knex('priorities as p')
157
-    .join('items as i', 'p.itemid', '=', 'i.id')
191
+    .join('items as i', 'p.itemname', '=', 'i.itemname')
158 192
     .leftJoin('specs as s', 'p.specid', '=', 's.id')
159 193
     .select('*') 
160 194
 
@@ -170,24 +204,24 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
170 204
         await this.admin
171 205
         .knex('priorities')
172 206
         .insert(<SRPriority>{
173
-            itemid: item.id,
207
+            itemname: item.itemname,
174 208
             ...priority
175 209
         })
176 210
     }
177 211
 
178 212
     getPriorities = async(itemname:string) : Promise<SRPriority[]> => {
179
-        const item = await this.getItem(itemname)
180
-
181
-        return await this.admin.knex('priorities')
182
-        .where('itemid', '=', item.id)
213
+        return await this.admin
214
+        .knex('priorities as p')
215
+        .where('p.itemname', '=', itemname)
183 216
         .select('*')
184 217
     }
185 218
 
186 219
     calculatePriorities = async (itemname: string, character:Character):Promise<number>=> {
187
-        const rules : SRPriority[] = await this.admin.knex('priorities as p')
220
+        const rules : SRPriority[] = await this.admin
221
+        .knex('priorities as p')
188 222
         .select('*')
189
-        .join('items as i', 'i.id', '=', 'p.itemid')
190
-        .where('itemname', '=', itemname)
223
+        .join('items as i', 'i.itemname', '=', 'p.itemname')
224
+        .where('p.itemname', '=', itemname)
191 225
 
192 226
         return rules.map(rule => {
193 227
             if(rule.specid && rule.race){
@@ -219,28 +253,37 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
219 253
         .knex('tokens as t')
220 254
         .select('*')
221 255
         .join('characters as c', 'c.id', '=', 't.characterid')
222
-        .join('items as i', 'i.id', '=', 't.itemid')
256
+        .join('items as i', 'i.itemname', '=', 't.itemname')
223 257
         .where({
224 258
             characterid: character.id,
225
-            itemid: item.id
259
+            "i.itemname": item.itemname
226 260
         })
227 261
         .first()
228 262
     }
229 263
 
230
-    getTokens = async (character:Character) : Promise<(SRToken & Character & Item)[]> => {
264
+    getTokens = async (character:Character, valid=true) : Promise<(SRToken & Character & Item)[]> => {
231 265
         return await this.admin
232 266
         .knex('tokens as t')
233 267
         .select('*')
234
-        .select('*')
235 268
         .join('characters as c', 'c.id', '=', 't.characterid')
236
-        .join('items as i', 'i.id', '=', 't.itemid')
269
+        .join('items as i', 'i.itemname', '=', 't.itemname')
237 270
         .where({
238 271
             characterid: character.id,
239 272
         })
273
+        .andWhere(function(){
274
+            if(valid){
275
+                this.whereNotNull('t.signupid')
276
+            }else{
277
+                this.whereNull('t.signupid')
278
+            }
279
+        })
240 280
     }
241 281
 
242 282
     countItems = async() :Promise<number> => {
243
-        const count = await this.admin.knex('items').count('*');
283
+        const count = await this.admin
284
+        .knex('items')
285
+        .count('*');
286
+        
244 287
         return <number>count[0]['count(*)']
245 288
     }
246 289
 
@@ -249,20 +292,24 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
249 292
         if(this.initialized) return
250 293
         this.initialized = true        
251 294
         
252
-        const allItems = [...T1, ...T2]
295
+        const itemTiers = allItems
253 296
 
254 297
         const countCache = await this.countItems()
255
-        getLogger('ItemManager').debug('Checking items, got: ',countCache, 'expected: ', allItems.length)
256 298
 
257
-        if(countCache != allItems.length){
258
-            const items:Item[] = await Promise.all(allItems.map((i) => this.fetchItem(i)))
259
-            try{
260
-                await this.admin
261
-                .knex('items')
262
-                .insert(items)
263
-            }catch(e){
264
-                getLogger('ItemManager').debug("Skipping item insertion")
265
-            }
299
+        if(countCache != Object.values(itemTiers).flat().length){
300
+            await Promise.all(
301
+                Object.entries(itemTiers)
302
+                .map((kv) => Promise.all(
303
+                    kv[1].map(i => this.fetchItem(i)
304
+                        .then(item => this.admin
305
+                            .knex('items')
306
+                            .insert({
307
+                                tier: kv[0],
308
+                                ...item
309
+                            })
310
+                    ))
311
+                ))
312
+            )
266 313
         }
267 314
     }
268 315
 }

+ 2
- 2
src/backend/Components/Raid/Interface.ts Целия файл

@@ -1,11 +1,11 @@
1
-import { Raid, Signup, Character, RaidData } from "../../Types/Types"
1
+import { Raid, Signup, Character, RaidData, User, Spec } from "../../Types/Types"
2 2
 
3 3
 export class IRaidManager{
4 4
     getRaids: () => Promise<Raid[]>
5 5
     createRaid: (raid:Raid) => Promise<any>
6 6
     addSignup: (signup: Signup) => Promise<any>
7 7
     removeSignup: (signup: Signup) => Promise<any>    
8
-    getSignups: (raid:Raid) => Promise<Signup[]>
8
+    getSignups: (raid:Raid) => Promise<(Signup & Character & Spec & User)[]>
9 9
     sign: (userToken: string, character:Character, raid:Raid, late:boolean) => Promise<any>
10 10
     unsign: (userToken: string, character:Character, raid:Raid,) => Promise<any>
11 11
     archiveRaid: (raid:Raid) => Promise<RaidData>

+ 47
- 24
src/backend/Components/Raid/RaidManager.ts Целия файл

@@ -1,11 +1,12 @@
1 1
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
2 2
 import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
3 3
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
-import { TableDefiniton, Signup, Raid, Character, RaidData, Spec, SRToken, Item } from "../../Types/Types";
4
+import { TableDefiniton, Signup, Raid, Character, RaidData, Spec, SRToken, Item, User } from "../../Types/Types";
5 5
 import { IAdmin } from "../../Admin/Interface";
6 6
 import { IRaidManager } from "./Interface";
7 7
 import { IUserManager } from "../User/Interface";
8 8
 import { ICharacterManager } from "../Character/Interface";
9
+import { _Tiers } from "../../Types/Items";
9 10
 
10 11
 @Injectable(IRaidManager)
11 12
 export class RaidManager
@@ -59,6 +60,7 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
59 60
                     table.string('description').notNullable()
60 61
                     table.string('title').notNullable()
61 62
                     table.integer('size').defaultTo(40)
63
+                    table.enu('tier', _Tiers).defaultTo(null as any)
62 64
                 }
63 65
             },{
64 66
                 name: 'archive',
@@ -69,7 +71,8 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
69 71
             },{
70 72
                 name: 'signups',
71 73
                 tableBuilder: (table) => {
72
-                    table.primary(['raidid', 'characterid'])
74
+                    table.increments('id').primary()
75
+                    table.unique(['raidid', 'characterid'])
73 76
                     table.integer('raidid')
74 77
                     table.foreign('raidid').references('id').inTable('raids').onDelete('CASCADE')
75 78
                     table.integer('characterid')
@@ -95,7 +98,7 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
95 98
         raid_id: signup.raidid, 
96 99
         character_id: signup.characterid
97 100
     })
98
-    .delete()
101
+    .del()
99 102
 
100 103
     getRaids = async () : Promise<Raid[]> => {
101 104
 
@@ -116,7 +119,6 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
116 119
 
117 120
     startRaid = async (raid:Raid) : Promise<RaidData> => {
118 121
         const archived = await this.archiveRaid(raid)
119
-
120 122
         delete archived.participants.late
121 123
 
122 124
         const giveCurrency = async (b: Character) => {
@@ -138,8 +140,17 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
138 140
         .insert({
139 141
             id:raidData.id,
140 142
             raiddata: JSON.stringify(raidData)
141
-        })
142
-        
143
+        })       
144
+
145
+        await Promise.all(
146
+            Object.values(raidData.participants).flat().flatMap((signup) =>  this.admin
147
+                .knex('tokens')
148
+                .where({
149
+                    characterid: signup.characterid,
150
+                    signupid: null
151
+                })
152
+                .del()
153
+        ))
143 154
 
144 155
         await this.admin.knex('raids')
145 156
         .where('id', '=', raid.id)
@@ -175,17 +186,17 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
175 186
     getRaidData = async (raid:Raid) : Promise<RaidData> => {
176 187
         const ret = {
177 188
             participants:{
178
-                Druid: <(Character&Spec)[]>[],
179
-                Hunter: <(Character&Spec)[]>[],
180
-                Mage: <(Character&Spec)[]>[],
181
-                Paladin: <(Character&Spec)[]>[],
182
-                Priest: <(Character&Spec)[]>[],
183
-                Rogue: <(Character&Spec)[]>[],
184
-                Shaman: <(Character&Spec)[]>[],
185
-                Warlock: <(Character&Spec)[]>[],
186
-                Warrior: <(Character&Spec)[]>[],
187
-                late: <(Character&Spec)[]>[],
188
-                bench: <(Character&Spec)[]>[],
189
+                Druid: <(Signup&Character&Spec)[]>[],
190
+                Hunter: <(Signup&Character&Spec)[]>[],
191
+                Mage: <(Signup&Character&Spec)[]>[],
192
+                Paladin: <(Signup&Character&Spec)[]>[],
193
+                Priest: <(Signup&Character&Spec)[]>[],
194
+                Rogue: <(Signup&Character&Spec)[]>[],
195
+                Shaman: <(Signup&Character&Spec)[]>[],
196
+                Warlock: <(Signup&Character&Spec)[]>[],
197
+                Warrior: <(Signup&Character&Spec)[]>[],
198
+                late: <(Signup&Character&Spec)[]>[],
199
+                bench: <(Signup&Character&Spec)[]>[],
189 200
             },
190 201
             tokens:{}
191 202
         }
@@ -205,9 +216,9 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
205 216
         .where('id','=',raid.id)
206 217
         .first()
207 218
 
208
-        const characterData: (Character & Spec & Signup)[] = await this.admin
219
+        const characterData: (Signup & Character & Spec)[] = await this.admin
209 220
         .knex('signups as s')
210
-        .select('characterid as id', 'charactername', 'class', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid')
221
+        .select('s.id as id', 'charactername', 'class', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid')
211 222
         .join('raids as r', 's.raidid','=','r.id')
212 223
         .join('characters as c', 's.characterid','=','c.id')
213 224
         .join('users as u', 'c.userid','=','u.id')
@@ -228,12 +239,15 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
228 239
 
229 240
         const tokenData: (Character & SRToken & Item)[] = await this.admin
230 241
         .knex('signups as s')
231
-        .select('*')
242
+        .select('*', 's.id as id')
232 243
         .join('raids as r', 's.raidid','=','r.id')
233 244
         .where('r.id','=',raid.id)
245
+        .andWhere(function(){
246
+            this.whereNotNull('t.signupid')
247
+        })
234 248
         .join('characters as c', 's.characterid','=','c.id')
235 249
         .join('tokens as t', 't.characterid','=','c.id')
236
-        .join('items as i', 'i.id','=','t.itemid')
250
+        .join('items as i', 'i.itemname','=','t.itemname')
237 251
 
238 252
         tokenData.forEach(data => {
239 253
             if(!ret.tokens[data.itemname])
@@ -246,12 +260,12 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
246 260
         }
247 261
     }
248 262
     
249
-    getSignups = async (raid:Raid) : Promise<Signup[]> => await this.admin
250
-    .knex('signups')
263
+    getSignups = async (raid:Raid) : Promise<(Signup & Character & Spec & User)[]> => await this.admin
264
+    .knex('signups as si')
251 265
     .join('characters as c', 'c.id', '=', 'characterid')
252 266
     .join('specs as s', 's.id', '=', 'specid')
253 267
     .join('users as u', 'u.id', '=', 'userid')
254
-    .select('*')
268
+    .select('*','si.id as id')
255 269
     .where('raidid', '=', raid.id!)
256 270
     
257 271
     sign = async (usertoken:string, character:Character, raid:Raid, late:boolean) => {
@@ -286,6 +300,15 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
286 300
                 late: late
287 301
             })
288 302
         }
303
+
304
+        return await this.admin
305
+        .knex('signups')
306
+        .select('*')
307
+        .where({
308
+            raidid: raid.id!,
309
+            characterid: character.id!,
310
+        })
311
+        .first()
289 312
     }
290 313
 
291 314
     unsign = async (usertoken:string, character:Character, raid:Raid) => {

+ 1
- 2
src/backend/Components/User/UserManager.ts Целия файл

@@ -118,14 +118,13 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
118 118
     initialize = async () => {
119 119
         this.exporters = [this.guild, this.item, this.raid, this.character] 
120 120
         //set up permissions
121
-        getLogger('UserManager').debug('inserting permissions')
121
+        getLogger('UserManager').debug('setting up permissions')
122 122
 
123 123
         await Promise.all( 
124 124
             [this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
125 125
             try{
126 126
                 await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions')
127 127
             }catch(e){
128
-                getLogger('UserManager').debug(feature.name);
129 128
             }
130 129
         })))
131 130
 

+ 17
- 1
src/backend/Types/Items.ts Целия файл

@@ -1,3 +1,6 @@
1
+export type Tiers = "MC" | 'BWL' | 'ZG' | 'AQ20' | 'AQ40' | 'Naxx'
2
+export const _Tiers = ["MC", 'BWL', 'ZG', 'AQ20', 'AQ40', 'Naxx']
3
+
1 4
 export const T1 = [
2 5
 "Robe of Volatile Power",
3 6
 "Salamander Scale Pants",
@@ -132,4 +135,17 @@ export const T2:string[] = [
132 135
 "Draconic Avenger",
133 136
 "Interlaced Shadow Jerkin",
134 137
 "Ringo's Blizzard Boots"
135
-]
138
+]
139
+
140
+export type AllItems = {
141
+    [tier in Tiers] : string[]
142
+}
143
+
144
+export const allItems : AllItems = {
145
+    MC: T1,
146
+    BWL: T2,
147
+    ZG:[],
148
+    AQ20: [],
149
+    AQ40: [],
150
+    Naxx: []
151
+}

+ 10
- 6
src/backend/Types/Types.ts Целия файл

@@ -6,6 +6,7 @@ import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/C
6 6
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface";
7 7
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
8 8
 import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
9
+import { Tiers } from "./Items";
9 10
 
10 11
 export type FrontcraftIfc = RaidManagerIfc
11 12
                           & UserManagerIfc
@@ -49,10 +50,10 @@ export type RPCPermission = {
49 50
 
50 51
 export type RaidData = Raid & {
51 52
     participants: {
52
-        [clazz in Class] : (Character & Spec)[] 
53
+        [clazz in Class] : (Signup & Character & Spec)[] 
53 54
     } & {
54
-        late: (Character & Spec)[]
55
-        bench: (Character & Spec)[] 
55
+        late: (Signup & Character & Spec)[]
56
+        bench: (Signup & Character & Spec)[] 
56 57
     }
57 58
     tokens: {
58 59
         [itemname in string]: (Character & SRToken & Item)[]
@@ -60,8 +61,9 @@ export type RaidData = Raid & {
60 61
 }
61 62
 
62 63
 export type SRToken = {
64
+    signupid?:number
63 65
     characterid: number,
64
-    itemid: number,
66
+    itemname: string,
65 67
     level: number
66 68
 }
67 69
 
@@ -69,18 +71,18 @@ export type SRPriority = {
69 71
     id?:number
70 72
     race?:Race
71 73
     specid?:number,
72
-    itemid?:number,
74
+    itemname?:string,
73 75
     description?:string,
74 76
     modifier:number
75 77
 }
76 78
 
77 79
 export type Item = {
78
-    id?:number
79 80
     itemname:string
80 81
     iconname:string
81 82
     url:string
82 83
     quality:string
83 84
     hidden:boolean
85
+    tier: Tiers
84 86
 }
85 87
 
86 88
 export type User = {
@@ -98,9 +100,11 @@ export type Raid = {
98 100
     start: string
99 101
     signupcount?: number
100 102
     size: number
103
+    tier: Tiers
101 104
 }
102 105
 
103 106
 export type Signup = {
107
+    id?:number
104 108
     raidid: number
105 109
     characterid: number
106 110
     benched: boolean

+ 15
- 3
src/frontend/src/app/frontcraft/pages/character/character.component.html Целия файл

@@ -1,13 +1,25 @@
1 1
 <nb-card 
2 2
 class = "col-12 col-xl-9"
3 3
 status="control">
4
-    <nb-card-header [ngStyle]="{'color': color}" style="text-transform: capitalize;">
5
-        {{char.charactername}}
4
+    <nb-card-header style="text-transform: capitalize;">
5
+        <h4>
6
+            <a *ngIf="link === 'character'" [ngStyle]="{'color': color}" [routerLink]="'/frontcraft/character/'+char.charactername">
7
+                {{char.charactername}}
8
+        </a>
9
+        </h4>
10
+        <h3>
11
+            <span [ngStyle]="{'color': color}" *ngIf="link !== 'character'">
12
+                {{char.charactername}}
13
+            </span>
14
+        </h3>
6 15
     </nb-card-header>
16
+
7 17
     <nb-card-body>
8 18
         {{char.race}}<br />
9 19
         {{char.specname}} {{char.class}}<br />
10
-        Owned by <a [routerLink]="'/frontcraft/user/'+char.username"> {{char.username}} ({{char.rank}})</a>
20
+        <span *ngIf="link === 'owner'">
21
+            Owned by <a [routerLink]="'/frontcraft/user/'+char.username"> {{char.username}} ({{char.rank}})</a>
22
+        </span>
11 23
         <br/><br />
12 24
         <span *ngFor="let token of tokens">
13 25
             [ {{token.level}} ]

+ 7
- 2
src/frontend/src/app/frontcraft/pages/character/character.component.ts Целия файл

@@ -1,4 +1,4 @@
1
-import { Component, OnInit } from '@angular/core';
1
+import { Component, OnInit, Input } from '@angular/core';
2 2
 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';
@@ -10,6 +10,9 @@ import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
10 10
 })
11 11
 export class FrontcraftCharacterComponent implements OnInit{
12 12
 
13
+    @Input() name?: string
14
+    @Input() link?: "owner" | "character" = 'owner'
15
+
13 16
     char : (Character & User & Spec) = {} as any
14 17
     color : string
15 18
     tokens
@@ -20,7 +23,9 @@ export class FrontcraftCharacterComponent implements OnInit{
20 23
     ){}
21 24
 
22 25
     async ngOnInit(){
23
-      const param = this.route.snapshot.paramMap.get('name');
26
+      const param = this.name || this.route.snapshot.paramMap.get('name');
27
+      if(!param) return
28
+      
24 29
       this.api.get('CharacterManager')      
25 30
       .getCharacterByName(param)
26 31
       .then((char) => {

+ 0
- 3
src/frontend/src/app/frontcraft/pages/characters/characters.component.html Целия файл

@@ -6,9 +6,6 @@
6 6
     </nb-card-body>
7 7
 </nb-card>
8 8
 
9
-
10
-
11
-
12 9
 <nb-card class="col-12 col-xl-9">
13 10
     <nb-card-body>
14 11
         <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true" />

+ 2
- 1
src/frontend/src/app/frontcraft/pages/pages.module.ts Целия файл

@@ -32,11 +32,12 @@ import { FrontcraftRaidComponent } from './raid/raid.component';
32 32
 import { FrontcraftArchiveComponent } from './raid/archive.component';
33 33
 import { NbEvaIconsModule } from '@nebular/eva-icons';
34 34
 import { FrontcraftCharacerpickerComponent } from './raid/characterpicker.component';
35
-import { FrontcraftShopComponent, FrontcraftBuyTokenComponent } from './shop/shop.component';
35
+import { FrontcraftShopComponent } from './shop/shop.component';
36 36
 import { FrontcraftRulesComponent } from './rules/rules.component';
37 37
 import { FrontcraftItemSelectComponent } from './shop/itemselector.component';
38 38
 import { NgxEchartsModule } from 'ngx-echarts';
39 39
 import { FrontcraftCharactersComponent } from './characters/characters.component';
40
+import { FrontcraftBuyTokenComponent } from './shop/buytoken.component';
40 41
 
41 42
 
42 43
 @NgModule({

+ 3
- 2
src/frontend/src/app/frontcraft/pages/raid/raid.component.html Целия файл

@@ -67,14 +67,15 @@
67 67
                                 </div>
68 68
                             </nb-card-body>
69 69
                         </nb-card>
70
-
71 70
                     </ng-container>
72 71
                 </div>
73 72
             </nb-tab>
73
+            <nb-tab tabTitle="Shop">
74
+                <shop (onSelect)="itemSelect($event)"></shop>
75
+            </nb-tab>
74 76
             <nb-tab tabTitle="Reserves">
75 77
                 <nb-list>
76 78
                     <nb-list-item *ngFor="let item of raid.tokens | keyvalue">
77
-                        
78 79
                         <a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}" 
79 80
                            target="_blank" 
80 81
                            [href]="item.value[0].url">

+ 14
- 3
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts Целия файл

@@ -5,6 +5,7 @@ import { RaidData, Raid, Signup } from '../../../../../../backend/Types/Types';
5 5
 import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
6 6
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
7 7
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
8
+import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
8 9
 
9 10
 @Component({
10 11
   selector: 'raid',
@@ -52,6 +53,15 @@ export class FrontcraftRaidComponent implements OnInit{
52 53
       this.refresh()
53 54
     }
54 55
 
56
+    itemSelect = async(item) => {
57
+      this.dialogService.open(FrontcraftBuyTokenComponent, {
58
+        context: {
59
+          item: item,
60
+          signup: this.mySignup
61
+        }
62
+      }).onClose.subscribe(() => this.refresh())
63
+    }
64
+
55 65
     signup = async () => {
56 66
       const signupFeature = this.api.get('signup')
57 67
       if(!signupFeature) return
@@ -60,7 +70,7 @@ export class FrontcraftRaidComponent implements OnInit{
60 70
         closeOnBackdropClick: true,
61 71
         closeOnEsc: true,
62 72
         context: {
63
-          'raid': this.raid,
73
+          raid: this.raid,
64 74
         } 
65 75
       }).onClose.subscribe(()=>{
66 76
         this.refresh()
@@ -83,7 +93,7 @@ export class FrontcraftRaidComponent implements OnInit{
83 93
       const signupFeature = this.api.get('signup')
84 94
       if(!signupFeature) return
85 95
 
86
-      await signupFeature.unsign(this.api.getAuth().token.value, this.mySignup, this.raid)
96
+      await signupFeature.unsign(this.api.getAuth().token.value, <any>{id: this.mySignup.characterid, userid: this.mySignup.userid}, this.raid)
87 97
       this.toast.show('Success', 'Unsigned', { status: 'success' })
88 98
       this.refresh()
89 99
     }
@@ -102,7 +112,8 @@ export class FrontcraftRaidComponent implements OnInit{
102 112
       })
103 113
       const user = this.api.getCurrentUser()
104 114
       const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
105
-      if(matchingSignup){
115
+      if(matchingSignup){       
116
+
106 117
         this.isSignedup = true
107 118
         this.mySignup = matchingSignup
108 119
         this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'

+ 1
- 1
src/frontend/src/app/frontcraft/pages/rules/rules.component.html Целия файл

@@ -4,7 +4,7 @@
4 4
             <nb-tab tabTitle="Info">
5 5
                 Smart text here
6 6
             </nb-tab>
7
-            <nb-tab *ngIf="managePriorities" tabTitle="priorities">
7
+            <nb-tab tabTitle="priorities">
8 8
                 <nb-list>
9 9
                     <nb-list-item *ngFor="let item of rules | keyvalue">
10 10
                         <a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}" 

+ 104
- 0
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts Целия файл

@@ -0,0 +1,104 @@
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: 'buyToken',
11
+    template: `
12
+    <nb-card class="col-12 col-xl-9">
13
+      <nb-card-header>
14
+        Buy {{item.itemname}}
15
+      </nb-card-header>
16
+      <nb-card-body>
17
+        <p>
18
+          You currently have {{currency}} softreserve currency
19
+        </p>  
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">
34
+            <button
35
+                (click)="buyToken(token.charactername)"
36
+                nbButton 
37
+                outline 
38
+                status="success" 
39
+                size="tiny">
40
+                buy
41
+            </button>
42
+            {{token.charactername}} [ {{token.level}} ] => [ {{token.level+1}} ]
43
+          </div>
44
+        </div>
45
+      </nb-card-body>
46
+  </nb-card>
47
+    
48
+    `,
49
+  })
50
+  export class FrontcraftBuyTokenComponent implements OnInit{
51
+  
52
+    @Input() item : Item
53
+    @Input() signup : Signup
54
+
55
+    @Input() tier: Tiers
56
+
57
+    characters: Character[]
58
+    modifier = {}
59
+    currency: number = 0
60
+    ownedtokens: SRToken[] = []
61
+  
62
+    constructor(
63
+      private toastr: NbToastrService,
64
+      protected dialogRef: NbDialogRef<FrontcraftBuyTokenComponent>,
65
+      private api : ApiService
66
+    ){}
67
+  
68
+    ngOnInit(): void {
69
+        const usr = this.api.getCurrentUser()
70
+        this.api.get('CharacterManager')
71
+        .getCharactersOfUser(usr.username)
72
+        .then(chars => {
73
+            chars.forEach(char => {
74
+                char['color'] = getClassColor(char.class)
75
+                this.api.get('ItemManager').getToken(char, this.item).then(token => {
76
+                  if(token) this.ownedtokens.push(token)
77
+                  else{
78
+                    this.api.get('ItemManager').calculatePriorities(this.item.itemname, char).then(modifier => {
79
+                      this.modifier[char.charactername] = modifier
80
+                    })
81
+                  }
82
+                })
83
+            })
84
+            this.characters = chars
85
+        })
86
+        this.api.get('UserManager').getUser(usr.username).then(u => {
87
+          if(!u) return
88
+          this.currency = u.currency
89
+        })
90
+    }
91
+  
92
+    buyToken = async (charactername:string) => {
93
+
94
+    const src = this.api.get('ItemManager')
95
+    const token = await src.buyToken(this.api.getAuth().token.value, charactername, this.item.itemname, this.signup)
96
+  
97
+    if(token){
98
+      this.toastr.show(token.characterid+' now has a token for '+token.itemname+' of level '+token.level, 'Yay', {status: 'success'})
99
+    }else{
100
+      this.toastr.show('Error (something went wrong)', 'Oh no', {status: 'danger'})
101
+    }
102
+    this.dialogRef.close()
103
+    }
104
+  }

+ 12
- 13
src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts Целия файл

@@ -1,4 +1,4 @@
1
-import { Component, OnInit } from '@angular/core';
1
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2 2
 import { ApiService } from '../../services/login-api';
3 3
 import { Item } from '../../../../../../backend/Types/Types';
4 4
 
@@ -10,10 +10,11 @@ export class FrontcraftItemSelectComponent implements OnInit{
10 10
 
11 11
     selected: Item
12 12
     search: string
13
-    items: any[] 
13
+    allItems:Item[] = []
14 14
     displayedItems: any[]
15 15
 
16
-    callbacks = []
16
+    @Input() items: string[]
17
+    @Output() onSelect = new EventEmitter<Item>();
17 18
 
18 19
     constructor(
19 20
       private api: ApiService,
@@ -21,25 +22,23 @@ export class FrontcraftItemSelectComponent implements OnInit{
21 22
     }
22 23
 
23 24
     async ngOnInit(){
24
-        this.api.get('ItemManager').getItems().then(items => {
25
-            this.items = items
26
-            this.displayedItems = items
25
+        Promise.all(this.items.map(itemname => 
26
+            this.api.get('ItemManager').getItem(itemname)
27
+        )).then(items => {
28
+            this.allItems = items
29
+            this.displayedItems = this.allItems
27 30
         })
28 31
     }
29 32
 
30 33
     changeSearch(){
31 34
         if(!this.search || this.search == "") 
32
-            this.displayedItems = this.items
35
+            this.displayedItems = this.allItems
33 36
         else
34
-            this.displayedItems = this.items.filter(it => it.itemname.toLowerCase().includes(this.search.toLowerCase()))
37
+            this.displayedItems = this.allItems.filter(it => it.itemname.toLowerCase().includes(this.search.toLowerCase()))
35 38
     }
36 39
 
37 40
     select(item: Item){
38
-        this.selected = item
39
-        this.callbacks.forEach(cb => cb(item))
41
+        this.onSelect.emit(item)
40 42
     }
41 43
 
42
-    onselect(callback:Function){
43
-        this.callbacks.push(callback)
44
-    }
45 44
 }

+ 6
- 12
src/frontend/src/app/frontcraft/pages/shop/shop.component.html Целия файл

@@ -1,13 +1,7 @@
1
+<h3>
2
+    {{tier}} items
3
+</h3>
1 4
 
2
-<nb-card class="col-12 col-xl-9">
3
-    <nb-card-body>
4
-        <nb-tabset>
5
-            <nb-tab tabTitle="Items">
6
-                <itemselect></itemselect>
7
-            </nb-tab>
8
-            <nb-tab tabTitle="About">
9
-            </nb-tab>
10
-        </nb-tabset>
11
-    </nb-card-body>
12
-</nb-card>
13
-
5
+<itemselect             
6
+[items]="allItems[tier]"
7
+(onSelect)="onSelect.emit($event)"></itemselect>

+ 11
- 26
src/frontend/src/app/frontcraft/pages/shop/shop.component.ts Целия файл

@@ -1,43 +1,28 @@
1
-import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit } from '@angular/core';
1
+import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
2 2
 import { ApiService as ApiService } from '../../services/login-api';
3 3
 import { FrontcraftItemSelectComponent } from './itemselector.component';
4 4
 import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
5
-import { Item, Character, SRToken } from '../../../../../../backend/Types/Types';
5
+import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
6 6
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
+import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
7 8
 
8 9
 @Component({
9 10
   selector: 'shop',
10 11
   templateUrl: './shop.component.html',
11 12
 })
12
-export class FrontcraftShopComponent implements AfterViewInit{
13
+export class FrontcraftShopComponent{
13 14
 
14
-    @ViewChild(FrontcraftItemSelectComponent, {static: false})
15
-    itemselect !: FrontcraftItemSelectComponent
15
+    @Input() character: Character
16
+    @Input() signup: Signup
17
+
18
+    @Input() tier = _Tiers[0]
19
+    @Output() onSelect = new EventEmitter<Item>()
20
+    allItems = allItems
16 21
 
17 22
     constructor(
18 23
       private api: ApiService,
19 24
       private dialogService : NbDialogService
20
-
21
-    ){
22
-      window['shop'] = this
23
-    }
24
-
25
-    buy = (item) => {
26
-      
27
-      this.dialogService.open(FrontcraftBuyTokenComponent, { 
28
-        closeOnBackdropClick: true,
29
-        closeOnEsc: true,
30
-        context: {
31
-          item: item
32
-        } 
33
-      }).onClose.subscribe(()=>{
34
-      });
35
-  
36
-    }
37
-
38
-    ngAfterViewInit(){
39
-      this.itemselect.onselect(this.buy)
40
-    }
25
+    ){}
41 26
 }
42 27
 
43 28
 @Component({

+ 3
- 27
src/frontend/src/app/frontcraft/pages/user/user.component.html Целия файл

@@ -7,32 +7,8 @@ accent="info">
7 7
     </nb-card-header>
8 8
     <nb-card-body>
9 9
         {{user.currency}}
10
-      <nb-card
11
-      accent="control"
12
-      *ngFor="let char of characters">
13
-          <nb-card-header>
14
-              <h4>
15
-                  <a [ngStyle]="{'color': char.color}" style="text-transform: capitalize;" [routerLink]="'/frontcraft/character/'+char.charactername">
16
-                      {{char.charactername}}
17
-                  </a>
18
-              </h4>
19
-          </nb-card-header>
20
-          <nb-card-body>
21
-            {{char.race}}<br />
22
-            {{char.specname}} {{char.class}}
23
-            <br />
24
-            <br />
25
-            <span *ngFor="let token of char.tokens">
26
-                [ {{token.level}} ]
27
-                <a [ngStyle]="{'color':token.quality=='Epic'?'#a335ee':'#ff8000'}" 
28
-                target="_blank" 
29
-                [href]="token.url">
30
-                <img style="min-width: 25px; width: 2.25vw; max-width: 50px" 
31
-                [src]="'https://wow.zamimg.com/images/wow/icons/large/'+token.iconname+'.jpg'" />
32
-                {{token.itemname}}
33
-                </a><br />
34
-            </span>
35
-          </nb-card-body>
36
-      </nb-card>
10
+      <ng-container *ngFor="let char of characters">
11
+          <character [name]="char.charactername" [link]="'character'"></character>
12
+      </ng-container>
37 13
     </nb-card-body>
38 14
 </nb-card>

+ 0
- 8
src/frontend/src/app/frontcraft/services/login-api.ts Целия файл

@@ -134,14 +134,6 @@ export class ApiService{
134 134
     }
135 135
 }
136 136
 
137
-function str2arraybuf(str:string): ArrayBuffer {
138
-    return new Buffer(str)
139
-  }
140
-  
141
-function buf2hex(buffer: ArrayBuffer) {
142
-    return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
143
-}
144
-
145 137
 export async function hash(value:string) : Promise<string>{
146 138
     return saltedHash(value, "")
147 139
 }

+ 22
- 12
test/backendTest.ts Целия файл

@@ -3,7 +3,7 @@ import { FrontworkAdmin } from "../src/backend/Admin/Admin";
3 3
 import { T1 } from "../src/backend/Types/Items";
4 4
 
5 5
 import { RPCSocket } from "rpclibrary";
6
-import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, SRPriority, Spec } from "../src/backend/Types/Types";
6
+import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, SRPriority, Spec, Signup } from "../src/backend/Types/Types";
7 7
 import { SpecT } from "../src/backend/Types/PlayerSpecs";
8 8
 
9 9
 
@@ -107,7 +107,7 @@ describe('Frontcraft', () => {
107 107
         client : RPCSocket & FrontcraftIfc,
108 108
         adminClient : RPCSocket & FrontcraftFeatureIfc,
109 109
         raids: Raid[] = [],
110
-        users : {[username in string] : { account: User, character: Character, auth: Auth, item?:string }} = {}
110
+        users : {[username in string] : { account: User, character: Character, auth: Auth, signup?:Signup, item?:string }} = {}
111 111
 
112 112
     const createAccount = (user: User) => {
113 113
         return client.UserManager.createUser(user)
@@ -217,9 +217,12 @@ describe('Frontcraft', () => {
217 217
             adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false).catch(done)
218 218
         )).then(x => {
219 219
             adminClient.signup.getSignups(raids[0]).then(s => {
220
-                if(s.length == testAccounts.length)
220
+                if(s.length == testAccounts.length){
221
+                    s.forEach(sign => {
222
+                        users[sign.username].signup = sign
223
+                    })
221 224
                     done()
222
-                else{
225
+                }else{
223 226
                     done("Unexpected number of signups: "+s.length)
224 227
                 }
225 228
             })
@@ -467,7 +470,7 @@ describe('Frontcraft', () => {
467 470
             const itemname = T1[0]//T1[Math.floor(T1.length*Math.random())]
468 471
             const modifier = await client.ItemManager.calculatePriorities(itemname, user.character)
469 472
 
470
-            const token = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname)
473
+            const token = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
471 474
             users[user.account.username].item = itemname
472 475
             
473 476
             if(!token) return false
@@ -480,7 +483,7 @@ describe('Frontcraft', () => {
480 483
     it('not buy token without currency', (done)=>{
481 484
         const user = Object.values(users)[0]
482 485
         const itemname = T1[0]
483
-        client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname).then(token => {
486
+        client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!).then(token => {
484 487
             if(!token) 
485 488
                 done()
486 489
             else {
@@ -497,12 +500,18 @@ describe('Frontcraft', () => {
497 500
             const item = await client.ItemManager.getItem(itemname)
498 501
             const before = await client.ItemManager.getToken(user.character, item)
499 502
             
500
-            if(!before || before.level !== 7) return
503
+            if(!before || before.level !== 7) {
504
+                console.log("expected level to be 7", before);
505
+                return
506
+            }
501 507
             
502
-            await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname)
503
-            const after = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname)
508
+            await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
509
+            const after = await client.ItemManager.buyToken(user.auth.token.value, user.character.charactername, itemname, user.signup!)
504 510
 
505
-            if(!after || after.level !== 9) return
511
+            if(!after || after.level !== 9) {
512
+                console.log("expected level to be 9", after);
513
+                return
514
+            }
506 515
             done()
507 516
         })
508 517
     })
@@ -510,11 +519,12 @@ describe('Frontcraft', () => {
510 519
     it('should buy more tokens', (done) => {
511 520
         Promise.all(Object.values(users).map(async (user) => {
512 521
             await adminClient.softreserveCurrency.incrementCurrency(user.account, 1)
513
-            await client.ItemManager
522
+            return await client.ItemManager
514 523
             .buyToken(
515 524
                 user.auth.token.value, 
516 525
                 user.character.charactername, 
517
-                T1[Math.floor(T1.length*Math.random())]
526
+                T1[Math.floor(T1.length*Math.random())],
527
+                user.signup!
518 528
             )
519 529
         })).then(_ => {
520 530
             done()

Loading…
Отказ
Запис