Browse Source

implement loot system feedback

master
peter 5 years ago
parent
commit
5ace7357a4

+ 7
- 0
src/backend/Admin/Admin.ts View File

102
     private startWebsocket(){
102
     private startWebsocket(){
103
         this.rpcServer = new RPCServer(20000, [
103
         this.rpcServer = new RPCServer(20000, [
104
             ...this.frontworkComponents,
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
             visibility: '0.0.0.0'
113
             visibility: '0.0.0.0'
107
         })
114
         })

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

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

+ 93
- 46
src/backend/Components/Item/ItemManager.ts View File

1
-import { T1, T2 } from "../../Types/Items";
1
+import { T1, T2, allItems, _Tiers } from "../../Types/Items";
2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
6
-import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec } from "../../Types/Types";
6
+import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup } from "../../Types/Types";
7
 import { IAdmin } from "../../Admin/Interface";
7
 import { IAdmin } from "../../Admin/Interface";
8
 import { IItemManager } from "./Interface";
8
 import { IItemManager } from "./Interface";
9
 import { getLogger } from "log4js";
9
 import { getLogger } from "log4js";
87
             {
87
             {
88
                 name: 'tokens',
88
                 name: 'tokens',
89
                 tableBuilder: (table) => {
89
                 tableBuilder: (table) => {
90
-                    table.primary(['characterid', 'itemid'])
90
+                    table.primary(['characterid', 'itemname'])
91
                     table.integer("characterid")
91
                     table.integer("characterid")
92
                     table.foreign("characterid").references("id").inTable('characters')
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
                     table.integer("level").defaultTo(1)
97
                     table.integer("level").defaultTo(1)
96
                 }
98
                 }
97
             },{
99
             },{
98
                 name: 'priorities',
100
                 name: 'priorities',
99
                 tableBuilder: (table) => {
101
                 tableBuilder: (table) => {
100
                     table.increments('id').primary()
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
                     table.string('race').nullable()
105
                     table.string('race').nullable()
104
                     table.integer('specid').nullable()
106
                     table.integer('specid').nullable()
105
                     table.foreign('specid').references('id').inTable('specs')
107
                     table.foreign('specid').references('id').inTable('specs')
109
             },{
111
             },{
110
                 name: 'items',
112
                 name: 'items',
111
                 tableBuilder: (table) => {
113
                 tableBuilder: (table) => {
112
-                    table.increments("id").primary()
113
-                    table.string('itemname').unique().notNullable()
114
+                    table.string('itemname').unique().notNullable().primary()
114
                     table.string('iconname').notNullable()
115
                     table.string('iconname').notNullable()
115
                     table.string('url').notNullable()
116
                     table.string('url').notNullable()
116
                     table.string('quality').defaultTo('Epic').notNullable()
117
                     table.string('quality').defaultTo('Epic').notNullable()
117
                     table.boolean('hidden').defaultTo(false).notNullable()
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
         const record = this.userManager.getUserRecordByToken(usertoken)
125
         const record = this.userManager.getUserRecordByToken(usertoken)
124
         const character = await this.character.getCharacterByName(charactername)
126
         const character = await this.character.getCharacterByName(charactername)
125
 
127
 
131
         const currency = await this.userManager.getCurrency(record.user)
133
         const currency = await this.userManager.getCurrency(record.user)
132
         if(currency < 1) return
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
         await this.userManager.decrementCurrency(record.user, 1)
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
                 characterid: character.id,
173
                 characterid: character.id,
142
-                itemid: item.id,
143
-                level: 1+modifier
174
+                itemname: item.itemname
144
             })
175
             })
145
         }else{
176
         }else{
146
-            await this.admin.knex('tokens').where({
177
+            await this.admin
178
+            .knex('tokens')
179
+            .insert({
147
                 characterid: character.id,
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
         return await this.getToken(character, item)
186
         return await this.getToken(character, item)
153
     }
187
     }
154
 
188
 
155
     getAllPriorities = async() :Promise<(SRPriority & Spec & Item)[]> => this.admin
189
     getAllPriorities = async() :Promise<(SRPriority & Spec & Item)[]> => this.admin
156
     .knex('priorities as p')
190
     .knex('priorities as p')
157
-    .join('items as i', 'p.itemid', '=', 'i.id')
191
+    .join('items as i', 'p.itemname', '=', 'i.itemname')
158
     .leftJoin('specs as s', 'p.specid', '=', 's.id')
192
     .leftJoin('specs as s', 'p.specid', '=', 's.id')
159
     .select('*') 
193
     .select('*') 
160
 
194
 
170
         await this.admin
204
         await this.admin
171
         .knex('priorities')
205
         .knex('priorities')
172
         .insert(<SRPriority>{
206
         .insert(<SRPriority>{
173
-            itemid: item.id,
207
+            itemname: item.itemname,
174
             ...priority
208
             ...priority
175
         })
209
         })
176
     }
210
     }
177
 
211
 
178
     getPriorities = async(itemname:string) : Promise<SRPriority[]> => {
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
         .select('*')
216
         .select('*')
184
     }
217
     }
185
 
218
 
186
     calculatePriorities = async (itemname: string, character:Character):Promise<number>=> {
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
         .select('*')
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
         return rules.map(rule => {
226
         return rules.map(rule => {
193
             if(rule.specid && rule.race){
227
             if(rule.specid && rule.race){
219
         .knex('tokens as t')
253
         .knex('tokens as t')
220
         .select('*')
254
         .select('*')
221
         .join('characters as c', 'c.id', '=', 't.characterid')
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
         .where({
257
         .where({
224
             characterid: character.id,
258
             characterid: character.id,
225
-            itemid: item.id
259
+            "i.itemname": item.itemname
226
         })
260
         })
227
         .first()
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
         return await this.admin
265
         return await this.admin
232
         .knex('tokens as t')
266
         .knex('tokens as t')
233
         .select('*')
267
         .select('*')
234
-        .select('*')
235
         .join('characters as c', 'c.id', '=', 't.characterid')
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
         .where({
270
         .where({
238
             characterid: character.id,
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
     countItems = async() :Promise<number> => {
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
         return <number>count[0]['count(*)']
287
         return <number>count[0]['count(*)']
245
     }
288
     }
246
 
289
 
249
         if(this.initialized) return
292
         if(this.initialized) return
250
         this.initialized = true        
293
         this.initialized = true        
251
         
294
         
252
-        const allItems = [...T1, ...T2]
295
+        const itemTiers = allItems
253
 
296
 
254
         const countCache = await this.countItems()
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 View File

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

+ 47
- 24
src/backend/Components/Raid/RaidManager.ts View File

1
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
1
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
2
 import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
2
 import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
3
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
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
 import { IAdmin } from "../../Admin/Interface";
5
 import { IAdmin } from "../../Admin/Interface";
6
 import { IRaidManager } from "./Interface";
6
 import { IRaidManager } from "./Interface";
7
 import { IUserManager } from "../User/Interface";
7
 import { IUserManager } from "../User/Interface";
8
 import { ICharacterManager } from "../Character/Interface";
8
 import { ICharacterManager } from "../Character/Interface";
9
+import { _Tiers } from "../../Types/Items";
9
 
10
 
10
 @Injectable(IRaidManager)
11
 @Injectable(IRaidManager)
11
 export class RaidManager
12
 export class RaidManager
59
                     table.string('description').notNullable()
60
                     table.string('description').notNullable()
60
                     table.string('title').notNullable()
61
                     table.string('title').notNullable()
61
                     table.integer('size').defaultTo(40)
62
                     table.integer('size').defaultTo(40)
63
+                    table.enu('tier', _Tiers).defaultTo(null as any)
62
                 }
64
                 }
63
             },{
65
             },{
64
                 name: 'archive',
66
                 name: 'archive',
69
             },{
71
             },{
70
                 name: 'signups',
72
                 name: 'signups',
71
                 tableBuilder: (table) => {
73
                 tableBuilder: (table) => {
72
-                    table.primary(['raidid', 'characterid'])
74
+                    table.increments('id').primary()
75
+                    table.unique(['raidid', 'characterid'])
73
                     table.integer('raidid')
76
                     table.integer('raidid')
74
                     table.foreign('raidid').references('id').inTable('raids').onDelete('CASCADE')
77
                     table.foreign('raidid').references('id').inTable('raids').onDelete('CASCADE')
75
                     table.integer('characterid')
78
                     table.integer('characterid')
95
         raid_id: signup.raidid, 
98
         raid_id: signup.raidid, 
96
         character_id: signup.characterid
99
         character_id: signup.characterid
97
     })
100
     })
98
-    .delete()
101
+    .del()
99
 
102
 
100
     getRaids = async () : Promise<Raid[]> => {
103
     getRaids = async () : Promise<Raid[]> => {
101
 
104
 
116
 
119
 
117
     startRaid = async (raid:Raid) : Promise<RaidData> => {
120
     startRaid = async (raid:Raid) : Promise<RaidData> => {
118
         const archived = await this.archiveRaid(raid)
121
         const archived = await this.archiveRaid(raid)
119
-
120
         delete archived.participants.late
122
         delete archived.participants.late
121
 
123
 
122
         const giveCurrency = async (b: Character) => {
124
         const giveCurrency = async (b: Character) => {
138
         .insert({
140
         .insert({
139
             id:raidData.id,
141
             id:raidData.id,
140
             raiddata: JSON.stringify(raidData)
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
         await this.admin.knex('raids')
155
         await this.admin.knex('raids')
145
         .where('id', '=', raid.id)
156
         .where('id', '=', raid.id)
175
     getRaidData = async (raid:Raid) : Promise<RaidData> => {
186
     getRaidData = async (raid:Raid) : Promise<RaidData> => {
176
         const ret = {
187
         const ret = {
177
             participants:{
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
             tokens:{}
201
             tokens:{}
191
         }
202
         }
205
         .where('id','=',raid.id)
216
         .where('id','=',raid.id)
206
         .first()
217
         .first()
207
 
218
 
208
-        const characterData: (Character & Spec & Signup)[] = await this.admin
219
+        const characterData: (Signup & Character & Spec)[] = await this.admin
209
         .knex('signups as s')
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
         .join('raids as r', 's.raidid','=','r.id')
222
         .join('raids as r', 's.raidid','=','r.id')
212
         .join('characters as c', 's.characterid','=','c.id')
223
         .join('characters as c', 's.characterid','=','c.id')
213
         .join('users as u', 'c.userid','=','u.id')
224
         .join('users as u', 'c.userid','=','u.id')
228
 
239
 
229
         const tokenData: (Character & SRToken & Item)[] = await this.admin
240
         const tokenData: (Character & SRToken & Item)[] = await this.admin
230
         .knex('signups as s')
241
         .knex('signups as s')
231
-        .select('*')
242
+        .select('*', 's.id as id')
232
         .join('raids as r', 's.raidid','=','r.id')
243
         .join('raids as r', 's.raidid','=','r.id')
233
         .where('r.id','=',raid.id)
244
         .where('r.id','=',raid.id)
245
+        .andWhere(function(){
246
+            this.whereNotNull('t.signupid')
247
+        })
234
         .join('characters as c', 's.characterid','=','c.id')
248
         .join('characters as c', 's.characterid','=','c.id')
235
         .join('tokens as t', 't.characterid','=','c.id')
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
         tokenData.forEach(data => {
252
         tokenData.forEach(data => {
239
             if(!ret.tokens[data.itemname])
253
             if(!ret.tokens[data.itemname])
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
     .join('characters as c', 'c.id', '=', 'characterid')
265
     .join('characters as c', 'c.id', '=', 'characterid')
252
     .join('specs as s', 's.id', '=', 'specid')
266
     .join('specs as s', 's.id', '=', 'specid')
253
     .join('users as u', 'u.id', '=', 'userid')
267
     .join('users as u', 'u.id', '=', 'userid')
254
-    .select('*')
268
+    .select('*','si.id as id')
255
     .where('raidid', '=', raid.id!)
269
     .where('raidid', '=', raid.id!)
256
     
270
     
257
     sign = async (usertoken:string, character:Character, raid:Raid, late:boolean) => {
271
     sign = async (usertoken:string, character:Character, raid:Raid, late:boolean) => {
286
                 late: late
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
     unsign = async (usertoken:string, character:Character, raid:Raid) => {
314
     unsign = async (usertoken:string, character:Character, raid:Raid) => {

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

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

+ 17
- 1
src/backend/Types/Items.ts View File

1
+export type Tiers = "MC" | 'BWL' | 'ZG' | 'AQ20' | 'AQ40' | 'Naxx'
2
+export const _Tiers = ["MC", 'BWL', 'ZG', 'AQ20', 'AQ40', 'Naxx']
3
+
1
 export const T1 = [
4
 export const T1 = [
2
 "Robe of Volatile Power",
5
 "Robe of Volatile Power",
3
 "Salamander Scale Pants",
6
 "Salamander Scale Pants",
132
 "Draconic Avenger",
135
 "Draconic Avenger",
133
 "Interlaced Shadow Jerkin",
136
 "Interlaced Shadow Jerkin",
134
 "Ringo's Blizzard Boots"
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 View File

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

+ 15
- 3
src/frontend/src/app/frontcraft/pages/character/character.component.html View File

1
 <nb-card 
1
 <nb-card 
2
 class = "col-12 col-xl-9"
2
 class = "col-12 col-xl-9"
3
 status="control">
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
     </nb-card-header>
15
     </nb-card-header>
16
+
7
     <nb-card-body>
17
     <nb-card-body>
8
         {{char.race}}<br />
18
         {{char.race}}<br />
9
         {{char.specname}} {{char.class}}<br />
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
         <br/><br />
23
         <br/><br />
12
         <span *ngFor="let token of tokens">
24
         <span *ngFor="let token of tokens">
13
             [ {{token.level}} ]
25
             [ {{token.level}} ]

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

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

+ 0
- 3
src/frontend/src/app/frontcraft/pages/characters/characters.component.html View File

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

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

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

+ 3
- 2
src/frontend/src/app/frontcraft/pages/raid/raid.component.html View File

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

+ 14
- 3
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts View File

5
 import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
5
 import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
6
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
6
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
7
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
8
+import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
8
 
9
 
9
 @Component({
10
 @Component({
10
   selector: 'raid',
11
   selector: 'raid',
52
       this.refresh()
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
     signup = async () => {
65
     signup = async () => {
56
       const signupFeature = this.api.get('signup')
66
       const signupFeature = this.api.get('signup')
57
       if(!signupFeature) return
67
       if(!signupFeature) return
60
         closeOnBackdropClick: true,
70
         closeOnBackdropClick: true,
61
         closeOnEsc: true,
71
         closeOnEsc: true,
62
         context: {
72
         context: {
63
-          'raid': this.raid,
73
+          raid: this.raid,
64
         } 
74
         } 
65
       }).onClose.subscribe(()=>{
75
       }).onClose.subscribe(()=>{
66
         this.refresh()
76
         this.refresh()
83
       const signupFeature = this.api.get('signup')
93
       const signupFeature = this.api.get('signup')
84
       if(!signupFeature) return
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
       this.toast.show('Success', 'Unsigned', { status: 'success' })
97
       this.toast.show('Success', 'Unsigned', { status: 'success' })
88
       this.refresh()
98
       this.refresh()
89
     }
99
     }
102
       })
112
       })
103
       const user = this.api.getCurrentUser()
113
       const user = this.api.getCurrentUser()
104
       const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
114
       const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
105
-      if(matchingSignup){
115
+      if(matchingSignup){       
116
+
106
         this.isSignedup = true
117
         this.isSignedup = true
107
         this.mySignup = matchingSignup
118
         this.mySignup = matchingSignup
108
         this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
119
         this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'

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

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

+ 104
- 0
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts View File

1
+import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
2
+import { ApiService as ApiService } from '../../services/login-api';
3
+import { FrontcraftItemSelectComponent } from './itemselector.component';
4
+import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
5
+import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
6
+import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
+import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
8
+
9
+@Component({
10
+    selector: '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 View File

1
-import { Component, OnInit } from '@angular/core';
1
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2
 import { ApiService } from '../../services/login-api';
2
 import { ApiService } from '../../services/login-api';
3
 import { Item } from '../../../../../../backend/Types/Types';
3
 import { Item } from '../../../../../../backend/Types/Types';
4
 
4
 
10
 
10
 
11
     selected: Item
11
     selected: Item
12
     search: string
12
     search: string
13
-    items: any[] 
13
+    allItems:Item[] = []
14
     displayedItems: any[]
14
     displayedItems: any[]
15
 
15
 
16
-    callbacks = []
16
+    @Input() items: string[]
17
+    @Output() onSelect = new EventEmitter<Item>();
17
 
18
 
18
     constructor(
19
     constructor(
19
       private api: ApiService,
20
       private api: ApiService,
21
     }
22
     }
22
 
23
 
23
     async ngOnInit(){
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
     changeSearch(){
33
     changeSearch(){
31
         if(!this.search || this.search == "") 
34
         if(!this.search || this.search == "") 
32
-            this.displayedItems = this.items
35
+            this.displayedItems = this.allItems
33
         else
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
     select(item: Item){
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 View File

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 View File

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
 import { ApiService as ApiService } from '../../services/login-api';
2
 import { ApiService as ApiService } from '../../services/login-api';
3
 import { FrontcraftItemSelectComponent } from './itemselector.component';
3
 import { FrontcraftItemSelectComponent } from './itemselector.component';
4
 import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
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
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
+import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
7
 
8
 
8
 @Component({
9
 @Component({
9
   selector: 'shop',
10
   selector: 'shop',
10
   templateUrl: './shop.component.html',
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
     constructor(
22
     constructor(
18
       private api: ApiService,
23
       private api: ApiService,
19
       private dialogService : NbDialogService
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
 @Component({
28
 @Component({

+ 3
- 27
src/frontend/src/app/frontcraft/pages/user/user.component.html View File

7
     </nb-card-header>
7
     </nb-card-header>
8
     <nb-card-body>
8
     <nb-card-body>
9
         {{user.currency}}
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
     </nb-card-body>
13
     </nb-card-body>
38
 </nb-card>
14
 </nb-card>

+ 0
- 8
src/frontend/src/app/frontcraft/services/login-api.ts View File

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
 export async function hash(value:string) : Promise<string>{
137
 export async function hash(value:string) : Promise<string>{
146
     return saltedHash(value, "")
138
     return saltedHash(value, "")
147
 }
139
 }

+ 22
- 12
test/backendTest.ts View File

3
 import { T1 } from "../src/backend/Types/Items";
3
 import { T1 } from "../src/backend/Types/Items";
4
 
4
 
5
 import { RPCSocket } from "rpclibrary";
5
 import { RPCSocket } from "rpclibrary";
6
-import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, SRPriority, Spec } 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
 import { SpecT } from "../src/backend/Types/PlayerSpecs";
7
 import { SpecT } from "../src/backend/Types/PlayerSpecs";
8
 
8
 
9
 
9
 
107
         client : RPCSocket & FrontcraftIfc,
107
         client : RPCSocket & FrontcraftIfc,
108
         adminClient : RPCSocket & FrontcraftFeatureIfc,
108
         adminClient : RPCSocket & FrontcraftFeatureIfc,
109
         raids: Raid[] = [],
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
     const createAccount = (user: User) => {
112
     const createAccount = (user: User) => {
113
         return client.UserManager.createUser(user)
113
         return client.UserManager.createUser(user)
217
             adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false).catch(done)
217
             adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false).catch(done)
218
         )).then(x => {
218
         )).then(x => {
219
             adminClient.signup.getSignups(raids[0]).then(s => {
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
                     done()
224
                     done()
222
-                else{
225
+                }else{
223
                     done("Unexpected number of signups: "+s.length)
226
                     done("Unexpected number of signups: "+s.length)
224
                 }
227
                 }
225
             })
228
             })
467
             const itemname = T1[0]//T1[Math.floor(T1.length*Math.random())]
470
             const itemname = T1[0]//T1[Math.floor(T1.length*Math.random())]
468
             const modifier = await client.ItemManager.calculatePriorities(itemname, user.character)
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
             users[user.account.username].item = itemname
474
             users[user.account.username].item = itemname
472
             
475
             
473
             if(!token) return false
476
             if(!token) return false
480
     it('not buy token without currency', (done)=>{
483
     it('not buy token without currency', (done)=>{
481
         const user = Object.values(users)[0]
484
         const user = Object.values(users)[0]
482
         const itemname = T1[0]
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
             if(!token) 
487
             if(!token) 
485
                 done()
488
                 done()
486
             else {
489
             else {
497
             const item = await client.ItemManager.getItem(itemname)
500
             const item = await client.ItemManager.getItem(itemname)
498
             const before = await client.ItemManager.getToken(user.character, item)
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
             done()
515
             done()
507
         })
516
         })
508
     })
517
     })
510
     it('should buy more tokens', (done) => {
519
     it('should buy more tokens', (done) => {
511
         Promise.all(Object.values(users).map(async (user) => {
520
         Promise.all(Object.values(users).map(async (user) => {
512
             await adminClient.softreserveCurrency.incrementCurrency(user.account, 1)
521
             await adminClient.softreserveCurrency.incrementCurrency(user.account, 1)
513
-            await client.ItemManager
522
+            return await client.ItemManager
514
             .buyToken(
523
             .buyToken(
515
                 user.auth.token.value, 
524
                 user.auth.token.value, 
516
                 user.character.charactername, 
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
         })).then(_ => {
529
         })).then(_ => {
520
             done()
530
             done()

Loading…
Cancel
Save