瀏覽代碼

checkpoint

master
peter 5 年之前
父節點
當前提交
b2707bb88f

+ 25
- 0
angular.json 查看文件

1
+{
2
+  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+  "version": 1,
4
+  "newProjectRoot": "projects",
5
+  "projects": {
6
+    "frontcraft": {
7
+      "projectType": "application",
8
+      "schematics": {},
9
+      "root": "",
10
+      "sourceRoot": "src/backend",
11
+      "prefix": "app",
12
+      "architect": {
13
+        "server": {
14
+          "builder": "@angular-devkit/build-angular:server",
15
+          "options": {
16
+            "outputPath": "dist/server",
17
+            "main": "src/backend/Launcher.ts",
18
+            "tsConfig": "tsconfig.server.json"
19
+          }
20
+        }
21
+      }
22
+    }
23
+  },
24
+  "defaultProject": "frontcraft"
25
+}

+ 5702
- 509
package-lock.json
文件差異過大導致無法顯示
查看文件


+ 13
- 4
package.json 查看文件

1
 {
1
 {
2
-  "name": "frontblock-admin",
3
-  "description": "Dynamic configurator for frontblock",
2
+  "name": "frontcraft",
3
+  "description": "Guild website framework",
4
   "version": "1.0.0",
4
   "version": "1.0.0",
5
   "scripts": {
5
   "scripts": {
6
     "tsc": "tsc",
6
     "tsc": "tsc",
9
     "start-backend": "npm run build-backend && npm run launch",
9
     "start-backend": "npm run build-backend && npm run launch",
10
     "test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js",
10
     "test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js",
11
     "build": "npm run build-backend && npm run build-frontend",
11
     "build": "npm run build-backend && npm run build-frontend",
12
-    "build-backend": "npm run clean-backend && tsc",
12
+    "build-backend": "npm run clean-backend && ng v && ng run frontcraft:server",
13
     "build-frontend": "npm run clean-frontend && (mkdir static || rm -rf static/*) && npm run build-dashboard",
13
     "build-frontend": "npm run clean-frontend && (mkdir static || rm -rf static/*) && npm run build-dashboard",
14
     "build-dashboard": "cd src/frontend && npm i && npm run build && cp -r dist/* ../../static",
14
     "build-dashboard": "cd src/frontend && npm i && npm run build && cp -r dist/* ../../static",
15
     "clean": "rm -rf data && npm run clean-backend && npm run clean-frontend",
15
     "clean": "rm -rf data && npm run clean-backend && npm run clean-frontend",
16
     "clean-backend": "rm -rf lib plugins config widget .rpt2_cache *.js *.ts",
16
     "clean-backend": "rm -rf lib plugins config widget .rpt2_cache *.js *.ts",
17
     "clean-frontend": "rm -rf src/frontend/dist static",
17
     "clean-frontend": "rm -rf src/frontend/dist static",
18
-    "webpack": "webpack --config src/backend/webpack.prod.js --progress --colors"
18
+    "webpack": "webpack --config src/backend/webpack.prod.js --progress --colors",
19
+    "setangular": "ng update @angular/cli@8.2.2 @angular/core@8.2.2 @angular/compiler-cli@8.2.2"
19
   },
20
   },
20
   "repository": {
21
   "repository": {
21
     "type": "git",
22
     "type": "git",
24
   "author": "frontblock.me",
25
   "author": "frontblock.me",
25
   "license": "ISC",
26
   "license": "ISC",
26
   "dependencies": {
27
   "dependencies": {
28
+    "@angular-devkit/build-angular": "^0.900.5",
29
+    "@angular/compiler": "^9.0.5",
30
+    "@angular/compiler-cli": "^9.0.5",
31
+    "@angular/platform-server": "^9.0.5",
32
+    "@nguniversal/express-engine": "^9.0.1",
33
+    "@nguniversal/module-map-ngfactory-loader": "^8.2.6",
27
     "@types/mocha": "^5.2.7",
34
     "@types/mocha": "^5.2.7",
35
+    "angular": "^1.7.9",
28
     "bsert": "0.0.10",
36
     "bsert": "0.0.10",
29
     "bsock": "^0.1.9",
37
     "bsock": "^0.1.9",
30
     "child-process-promise": "^2.2.1",
38
     "child-process-promise": "^2.2.1",
56
     "xml2js": "^0.4.22"
64
     "xml2js": "^0.4.22"
57
   },
65
   },
58
   "devDependencies": {
66
   "devDependencies": {
67
+    "@angular/cli": "^9.0.5",
59
     "@types/express": "^4.17.0",
68
     "@types/express": "^4.17.0",
60
     "@types/node": "^11.13.19",
69
     "@types/node": "^11.13.19",
61
     "@types/semver": "^6.0.1",
70
     "@types/semver": "^6.0.1",

+ 22
- 0
src/backend/Admin/Admin.ts 查看文件

22
 import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
22
 import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
23
 import { PubSub } from '../Components/PubSub/PubSub';
23
 import { PubSub } from '../Components/PubSub/PubSub';
24
 
24
 
25
+import { ngExpressEngine } from '@nguniversal/express-engine';
26
+import { APP_BASE_HREF } from '@angular/common';
27
+import { AppServerModule } from './app.server.module';
28
+
25
 
29
 
26
 const logger = getLogger("admin", 'debug') 
30
 const logger = getLogger("admin", 'debug') 
27
 
31
 
132
         this.express = express()
136
         this.express = express()
133
         this.express.use('/', express.static('static'))
137
         this.express.use('/', express.static('static'))
134
 
138
 
139
+
140
+        this.express.engine('html', ngExpressEngine({
141
+            bootstrap: AppServerModule,
142
+        }));
143
+    
144
+        this.express.set('view engine', 'html');
145
+        this.express.set('views', 'static');
146
+        
147
+          // Serve static files from /browser
148
+        this.express.get('*.*', express.static('static', {
149
+            maxAge: '1y'
150
+        }));
151
+        
152
+          // All regular routes use the Universal engine
153
+        this.express.get('*', (req, res) => {
154
+            res.render('index', { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
155
+        });
156
+
135
         /**
157
         /**
136
          * get the compiled FrontendPlugins.js
158
          * get the compiled FrontendPlugins.js
137
          */
159
          */

+ 19
- 0
src/backend/Admin/app.server.module.ts 查看文件

1
+import { NgModule } from '@angular/core';
2
+import { ServerModule } from '@angular/platform-server';
3
+import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
4
+
5
+import { AppModule } from '../../frontend/src/app/app.module';
6
+import { AppComponent } from '../../frontend/src/app/app.component';
7
+
8
+@NgModule({
9
+  imports: [
10
+    AppModule,
11
+    ServerModule,
12
+    ModuleMapLoaderModule
13
+  ],
14
+  providers: [
15
+    // Add universal-only providers here
16
+  ],
17
+  bootstrap: [ AppComponent ],
18
+})
19
+export class AppServerModule {}

+ 2
- 6
src/backend/Components/Guild/GuildManager.ts 查看文件

2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
2
 import { Inject, Injectable } from "../../Injector/ServiceDecorator";
3
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "./RPCInterface";
3
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "./RPCInterface";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
5
-import { _Rank, Rank } from "../../Types/Types";
5
+import { _Rank, Rank, Guild } from "../../Types/Types";
6
 import { IAdmin } from "../../Admin/Interface";
6
 import { IAdmin } from "../../Admin/Interface";
7
 import { IGuildManager } from "./Interface";
7
 import { IGuildManager } from "./Interface";
8
 
8
 
9
-export type Guild = {
10
-    name: string
11
-    realm: string
12
-    description: string
13
-};
9
+
14
 
10
 
15
 @Injectable(IGuildManager)
11
 @Injectable(IGuildManager)
16
 export class GuildManager
12
 export class GuildManager

+ 1
- 2
src/backend/Components/Guild/Interface.ts 查看文件

1
-import { Rank } from "../../Types/Types"
2
-import { Guild } from "./GuildManager"
1
+import { Rank, Guild } from "../../Types/Types"
3
 
2
 
4
 export class IGuildManager{
3
 export class IGuildManager{
5
     getHeadCount: () => Promise<{rank:Rank, count: number}[]>
4
     getHeadCount: () => Promise<{rank:Rank, count: number}[]>

+ 2
- 1
src/backend/Components/Item/Interface.ts 查看文件

3
 
3
 
4
 export class IItemManager{
4
 export class IItemManager{
5
     getItems: () => Promise<Item[]>
5
     getItems: () => Promise<Item[]>
6
-    fetchItem: (name:string) => Promise<Item>
6
+    getItem: (name:string, tier?:Tiers) => Promise<Item | undefined>
7
+    fetchItem: (name:string, tier?:Tiers) => Promise<Item | undefined>
7
     buyToken: (usertoken: string, charactername:string, itemname:string, signup:Signup) => Promise<(SRToken & Character & Item) | undefined>
8
     buyToken: (usertoken: string, charactername:string, itemname:string, signup:Signup) => Promise<(SRToken & Character & Item) | undefined>
8
     setPriority: (itemname:string, priority: any) => Promise<void>
9
     setPriority: (itemname:string, priority: any) => Promise<void>
9
     calculatePriorities: (itemname: string, character:Character) => Promise<number>
10
     calculatePriorities: (itemname: string, character:Character) => Promise<number>

+ 96
- 27
src/backend/Components/Item/ItemManager.ts 查看文件

3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
6
-import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup, Raid } from "../../Types/Types";
6
+import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup, Raid, Stats } 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";
10
 import { IUserManager } from "../User/Interface";
9
 import { IUserManager } from "../User/Interface";
11
 import { ICharacterManager } from "../Character/Interface";
10
 import { ICharacterManager } from "../Character/Interface";
12
 import { IPubSub } from "../PubSub/Interface";
11
 import { IPubSub } from "../PubSub/Interface";
13
 import { IRaidManager } from "../Raid/Interface";
12
 import { IRaidManager } from "../Raid/Interface";
13
+import { getLogger } from "frontblock-generic/Types";
14
 
14
 
15
 const fetch = require('node-fetch')
15
 const fetch = require('node-fetch')
16
 const xml2js = require('xml2js');
16
 const xml2js = require('xml2js');
60
     }]
60
     }]
61
 
61
 
62
     notifyRaid = async (raid: Raid | { id: number }) => {
62
     notifyRaid = async (raid: Raid | { id: number }) => {
63
-        const data = await this.raidManager.getRaidData(<Raid>raid)
64
-        this.pubsub.publish("" + raid.id, data)
65
         await this.notifyRaids()
63
         await this.notifyRaids()
64
+        const data = await this.raidManager.getRaidData(<Raid>raid)
65
+        await this.pubsub.publish("" + raid.id, data)
66
     }
66
     }
67
 
67
 
68
     notifyRaids = async () => {
68
     notifyRaids = async () => {
69
-        this.pubsub.publish('raids', undefined)
69
+        await this.pubsub.publish('raids', undefined)
70
     }
70
     }
71
 
71
 
72
     wipeCurrencyAndItems = async () => {
72
     wipeCurrencyAndItems = async () => {
78
 
78
 
79
     getItems = async (): Promise<Item[]> => await this.admin.knex.select('*').from('items')
79
     getItems = async (): Promise<Item[]> => await this.admin.knex.select('*').from('items')
80
 
80
 
81
-    getItem = async (name: string): Promise<Item> => {
82
-        return await this.admin.knex('items').select('*').where('itemname', '=', name).first()
81
+    getItem = async (name: string, tier?:Tiers): Promise<Item | undefined> => {
82
+        let item = await this.admin.knex('items').select('*').where('itemname', '=', name).first()
83
+        if(!item){
84
+            item = await this.fetchItem(name, tier)
85
+            if (!item)
86
+                return
87
+            
88
+            await this.admin
89
+                .knex('items')
90
+                .insert({
91
+                    ...item,
92
+                    stats: JSON.stringify(item.stats)
93
+                })
94
+
95
+            return this.getItem(name, tier)
96
+        }
97
+
98
+        item.stats = JSON.parse(item.stats)
99
+        return item
83
     }
100
     }
84
 
101
 
85
-    fetchItem = async (name: string): Promise<Item> => {
102
+    fetchItem = async (name: string, tier?:Tiers): Promise<Item | undefined> => {
86
         const res = await fetch('https://classic.wowhead.com/item=' + name + '&xml');
103
         const res = await fetch('https://classic.wowhead.com/item=' + name + '&xml');
87
         const txt = await res.text();
104
         const txt = await res.text();
88
         const r = await parser.parseStringPromise(txt);
105
         const r = await parser.parseStringPromise(txt);
106
+        try{
107
+            if(!r.wowhead.item || !r.wowhead.item[0]) 
108
+                return
109
+
110
+            const j = JSON.parse('{'+r.wowhead.item[0].json[0]+"}")
111
+            if(!tier){
112
+                if(j.sourcemore && Number.isInteger(j.sourcemore[0].t) && j.sourcemore[0].t > 0){
113
+                    tier = _Tiers[j.sourcemore[0].t-1]
114
+                }else{
115
+                    tier = "MC"
116
+                }
117
+            }
118
+            const stats = JSON.parse('{'+r.wowhead.item[0].jsonEquip[0]+"}")
89
 
119
 
90
-        try {
91
-            return <Item>{
120
+            const item =  <Item>{
92
                 itemname: r.wowhead.item[0].name[0],
121
                 itemname: r.wowhead.item[0].name[0],
93
                 iconname: r.wowhead.item[0].icon[0]._,
122
                 iconname: r.wowhead.item[0].icon[0]._,
94
                 url: r.wowhead.item[0].link[0],
123
                 url: r.wowhead.item[0].link[0],
95
                 quality: r.wowhead.item[0].quality[0]._,
124
                 quality: r.wowhead.item[0].quality[0]._,
96
-                tooltip: r.wowhead.item[0].htmlTooltip[0]
125
+                tooltip: r.wowhead.item[0].htmlTooltip[0],
126
+                stats: toStats(stats),
127
+                tier: tier
97
             }
128
             }
98
-        } catch (e) {
99
-            console.log(name)
100
-            throw e
129
+            return item
130
+
131
+        }catch(e){
132
+            getLogger('ItemManager', 'error').error(name, e);
101
         }
133
         }
102
     }
134
     }
103
 
135
 
139
                     table.boolean('hidden').defaultTo(false).notNullable()
171
                     table.boolean('hidden').defaultTo(false).notNullable()
140
                     table.string('tooltip').notNullable()
172
                     table.string('tooltip').notNullable()
141
                     table.enu('tier', _Tiers).notNullable()
173
                     table.enu('tier', _Tiers).notNullable()
174
+                    table.json('stats').notNullable()
142
                 }
175
                 }
143
             }]
176
             }]
144
     }
177
     }
249
         await this.admin
282
         await this.admin
250
             .knex('priorities')
283
             .knex('priorities')
251
             .insert(<SRPriority>{
284
             .insert(<SRPriority>{
252
-                itemname: item.itemname,
285
+                itemname: item!.itemname,
253
                 ...priority
286
                 ...priority
254
             })
287
             })
255
     }
288
     }
354
         if (countCache != Object.values(itemTiers).flat().length) {
387
         if (countCache != Object.values(itemTiers).flat().length) {
355
             await Promise.all(
388
             await Promise.all(
356
                 Object.entries(itemTiers)
389
                 Object.entries(itemTiers)
357
-                    .map((kv) => Promise.all(
358
-                        kv[1].map(i => this.fetchItem(i)
359
-                            .then(item =>
360
-                                this.admin
361
-                                    .knex('items')
362
-                                    .insert({
363
-                                        tier: kv[0],
364
-                                        ...item
365
-                                    }).catch(() => { })
366
-                            )
367
-                        )
390
+                    .map((kv: [string, string[]]) => Promise.all(
391
+                        kv[1].map(i => this.getItem(i, kv[0] as Tiers)                        )
368
                     ))
392
                     ))
369
             )
393
             )
370
         }
394
         }
371
     }
395
     }
372
-}
396
+}
397
+
398
+function toStats(obj:any){
399
+    if(!obj) obj = {}
400
+    return {
401
+      stamina: obj.sta || 0,
402
+      agility: obj.agi || 0,
403
+      strength: obj.str || 0,
404
+      intellect: obj.int || 0,
405
+      spirit: obj.spi || 0,
406
+  
407
+      attackpower: obj.atkpwr || 0,
408
+  
409
+      meleehit: obj.mlehitpct || 0,
410
+      meleecrit: obj.mlecritstrkpct || 0,
411
+  
412
+      rangeattackpower: obj.rgdatkpwr || 0,
413
+      rangehit: obj.rgdhitpct || 0,
414
+      rangecrit: obj.rgdcritstrkpct || 0,
415
+  
416
+      spellpower: obj.splpwr || 0,
417
+      spellhit: obj.splhitpct || 0,
418
+      spellcrit: obj.splcritstrkpct || 0,
419
+      heal: obj.splheal || 0,
420
+
421
+      frostspellpower: obj.frosplpwr || 0,
422
+      firespellpower: obj.firsplpwr || 0,
423
+      naturespellpower: obj.natsplpwr || 0,
424
+      shadowspellpower: obj.shasplpwr || 0,
425
+      arcanespellpower: obj.arcsplpwr || 0,
426
+  
427
+      fireresist: obj.firres || 0,
428
+      arcaneresist: obj.arcres || 0,
429
+      frostresist: obj.frores || 0,
430
+      natureresist: obj.natres || 0,
431
+      shadowresist: obj.shares || 0,
432
+      
433
+      armor: obj.armor || 0,
434
+      defense: obj.def || 0,
435
+      block: obj.blockpct || 0,
436
+      blockvalue: obj.blockamount || 0,
437
+      dodge: obj.dodgepct || 0,
438
+      parry: obj.parrypct || 0,
439
+    } as Stats
440
+    
441
+  }

+ 1
- 1
src/backend/Components/Item/RPCInterface.ts 查看文件

2
 
2
 
3
 export type ItemManagerIfc = {
3
 export type ItemManagerIfc = {
4
     ItemManager: {
4
     ItemManager: {
5
-        getItem: IItemManager['fetchItem']
5
+        getItem: IItemManager['getItem']
6
         getItems: IItemManager['getItems']
6
         getItems: IItemManager['getItems']
7
         buyToken: IItemManager['buyToken']
7
         buyToken: IItemManager['buyToken']
8
         calculatePriorities: IItemManager['calculatePriorities']
8
         calculatePriorities: IItemManager['calculatePriorities']

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

70
 "Cenarion Bracers",
70
 "Cenarion Bracers",
71
 "Cenarion Vestments",
71
 "Cenarion Vestments",
72
 "Cenarion Helm",
72
 "Cenarion Helm",
73
-"Cenarion Helm",
74
 "Cenarion Leggings",
73
 "Cenarion Leggings",
75
 "Cenarion Spaulders",
74
 "Cenarion Spaulders",
76
 "Giantstalker's Belt",
75
 "Giantstalker's Belt",
106
 "Robes of Prophecy",
105
 "Robes of Prophecy",
107
 "Vambraces of Prophecy",
106
 "Vambraces of Prophecy",
108
 "Nightslayer Belt",
107
 "Nightslayer Belt",
109
-"Nightslayer Belt",
110
 "Nightslayer Bracelets",
108
 "Nightslayer Bracelets",
111
 "Nightslayer Chestpiece",
109
 "Nightslayer Chestpiece",
112
 "Nightslayer Cover",
110
 "Nightslayer Cover",
120
 "Felheart Robes",
118
 "Felheart Robes",
121
 "Felheart Shoulder Pads",
119
 "Felheart Shoulder Pads",
122
 "Felheart Horns",
120
 "Felheart Horns",
123
-"Felheart Horns",
124
 "Belt of Might",
121
 "Belt of Might",
125
 "Bracers of Might",
122
 "Bracers of Might",
126
 "Breastplate of Might",
123
 "Breastplate of Might",
150
 "Bloodfang Hood",
147
 "Bloodfang Hood",
151
 "Bloodfang Pants",
148
 "Bloodfang Pants",
152
 "Helmet of Ten Storms",
149
 "Helmet of Ten Storms",
153
-"Helmet of Ten Storms",
154
 "Nemesis Skullcap",
150
 "Nemesis Skullcap",
155
 "Nemesis Leggings",
151
 "Nemesis Leggings",
156
 "Helm of Wrath",
152
 "Helm of Wrath",

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

81
     modifier:number
81
     modifier:number
82
 }
82
 }
83
 
83
 
84
+export type Stats = {
85
+    stamina: number,
86
+    agility: number,
87
+    strength: number,
88
+    intellect: number,
89
+    spirit: number,
90
+  
91
+    fireresist: number,
92
+    frostresist: number,
93
+    arcaneresist: number,
94
+    shadowresist: number,
95
+    natureresist: number,
96
+
97
+    spellpower: number,
98
+    spellhit: number,
99
+    spellcrit: number,
100
+    heal: number,
101
+
102
+    frostspellpower:  number,
103
+    firespellpower: number,
104
+    naturespellpower: number,
105
+    shadowspellpower: number,
106
+    arcanespellpower: number,
107
+
108
+    attackpower: number,
109
+  
110
+    meleehit: number,
111
+    meleecrit: number,
112
+
113
+    rangeattackpower: number,
114
+    rangehit: number,
115
+    rangecrit: number,
116
+  
117
+    armor:number,
118
+    defense: number,
119
+    block: number,
120
+    blockvalue: number,
121
+    parry: number,
122
+    dodge:number
123
+}
124
+
125
+export type Guild = {
126
+    name: string
127
+    realm: string
128
+    description: string
129
+};
130
+
84
 export type Item = {
131
 export type Item = {
85
     itemname:string
132
     itemname:string
86
     iconname:string
133
     iconname:string
89
     hidden:boolean
136
     hidden:boolean
90
     tooltip: string
137
     tooltip: string
91
     tier: Tiers
138
     tier: Tiers
139
+    stats: Stats
92
 }
140
 }
93
 
141
 
94
 export type User = {
142
 export type User = {

+ 1
- 1
src/frontend/package.json 查看文件

13
     "ng": "ng",
13
     "ng": "ng",
14
     "conventional-changelog": "conventional-changelog",
14
     "conventional-changelog": "conventional-changelog",
15
     "start": "ng serve",
15
     "start": "ng serve",
16
-    "build": "ng build",
16
+    "build": "ng build --aot",
17
     "build:prod": "npm run build -- --prod --aot",
17
     "build:prod": "npm run build -- --prod --aot",
18
     "test": "ng test",
18
     "test": "ng test",
19
     "test:coverage": "rimraf coverage && npm run test -- --code-coverage",
19
     "test:coverage": "rimraf coverage && npm run test -- --code-coverage",

+ 1
- 2
src/frontend/src/app/@theme/components/header/header.component.html 查看文件

31
     <nb-action class="user-action">
31
     <nb-action class="user-action">
32
       <nb-user [nbContextMenu]="userMenu"
32
       <nb-user [nbContextMenu]="userMenu"
33
                [onlyPicture]="false"
33
                [onlyPicture]="false"
34
-               [name]="user?.username"
35
-               [picture]="user?.picture">
34
+               [name]="user?.username">
36
       </nb-user>
35
       </nb-user>
37
     </nb-action>
36
     </nb-action>
38
 
37
 

+ 1
- 0
src/frontend/src/app/frontcraft/auth/register/register.component.ts 查看文件

29
   selectedSpec = specs[this.selectedClass][0]
29
   selectedSpec = specs[this.selectedClass][0]
30
   specs = specs[this.selectedClass]
30
   specs = specs[this.selectedClass]
31
   showApplication = false
31
   showApplication = false
32
+  submitted = false
32
 
33
 
33
   constructor(
34
   constructor(
34
     private router : Router,  
35
     private router : Router,  

+ 67
- 51
src/frontend/src/app/frontcraft/pages/armory/armory.component.ts 查看文件

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
-import { Item } from '../../../../../../backend/Types/Types';
2
+import { Item, Stats } from '../../../../../../backend/Types/Types';
3
+
3
 import { NbToastrService } from '@nebular/theme';
4
 import { NbToastrService } from '@nebular/theme';
5
+import { ApiService } from '../../services/login-api';
4
 
6
 
5
 @Component({
7
 @Component({
6
   selector: 'armory',
8
   selector: 'armory',
7
   templateUrl: './armory.component.html',
9
   templateUrl: './armory.component.html',
8
 })
10
 })
9
-export class FrontcraftArmoryComponent implements OnInit{
11
+export class FrontcraftArmoryComponent implements OnInit {
10
 
12
 
11
   servers = servers
13
   servers = servers
14
+  submitted = false
12
   charactername = ""
15
   charactername = ""
13
   server = "Gandling"
16
   server = "Gandling"
14
   region = "EU"
17
   region = "EU"
15
-  gear:string[] = []
18
+  gear: Item[] = []
16
 
19
 
17
   constructor(
20
   constructor(
21
+    private api: ApiService,
18
     private toastr: NbToastrService
22
     private toastr: NbToastrService
19
-  ){}
23
+  ) { }
20
 
24
 
21
-  async submit(){
22
-    const dataLink = "https://classic.warcraftlogs.com:443/v1/parses/character/"+this.charactername.toLowerCase().replace(/^\w/, c => c.toUpperCase())+"/"+this.server+"/"+this.region+"?api_key=c698515ab4f592cdb848d80b3abe616c&metric=dps"
25
+  async submit() {
26
+    const dataLink = "https://classic.warcraftlogs.com:443/v1/parses/character/" + this.charactername.toLowerCase().replace(/^\w/, c => c.toUpperCase()) + "/" + this.server + "/" + this.region + "?api_key=c698515ab4f592cdb848d80b3abe616c&metric=dps"
23
 
27
 
24
-    fetch(dataLink).then(raw => raw.json().then((json:any[]) => {
25
-      if(json.length < 1) return
28
+    fetch(dataLink).then(raw => raw.json().then(async (json: any[]) => {
29
+      if (json.length < 1) return
26
       let min = -1
30
       let min = -1
27
       let data
31
       let data
28
 
32
 
29
-      for(let i = json.length-1; i > 0; i--){
30
-        if(json[i].startTime > min && json[i].gear[0].name != "Unknown Item"){
33
+      for (let i = json.length - 1; i > 0; i--) {
34
+        if (json[i].startTime > min && json[i].gear[0].name != "Unknown Item") {
31
           data = json[i]
35
           data = json[i]
32
           break
36
           break
33
         }
37
         }
34
       }
38
       }
35
-      if(!data){
39
+      if (!data) {
36
         this.toastr.danger('Unknown character, or no warcraftlogs', "Error", {
40
         this.toastr.danger('Unknown character, or no warcraftlogs', "Error", {
37
           duration: 2000
41
           duration: 2000
38
-        })  
42
+        })
39
         return
43
         return
40
       }
44
       }
41
 
45
 
42
-      this.gear = data.gear.map(item => {return <Item>{
43
-        itemname: item.name,
44
-        iconname: item.icon.replace('.jpg', ''),
45
-        quality: item.quality.replace(/^\w/, c => c.toUpperCase()),
46
-        url: "https://classic.wowhead.com/item="+item.id,
47
-      }}).filter(item => item.itemname != "Unknown Item")
46
+      const maybeItems: (Item | undefined)[] = await Promise.all(data.gear
47
+        .filter(item => item.name != "Unknown Item")
48
+        .map(async item => await this.api.get('ItemManager').getItem(item.name)))
49
+
50
+      const geardata = maybeItems.filter(maybeItem => maybeItem != null)
51
+
52
+      this.gear = geardata
53
+      console.log(this.gear.map(g => g.stats).reduce(sumStats))
48
     }))
54
     }))
49
   }
55
   }
50
 
56
 
51
-  async ngOnInit(){
57
+  async ngOnInit() {
52
 
58
 
53
   }
59
   }
54
 }
60
 }
55
 
61
 
62
+function sumStats(stat1: Stats, stat2: Stats):Stats{
63
+  const ret = {} as any
64
+  Object.keys(stat1).forEach(key => {
65
+    ret[key] = stat1[key] + stat2[key]
66
+  })
67
+  return ret
68
+}
69
+
70
+
71
+
56
 const servers = [
72
 const servers = [
57
   "Ashbringer"
73
   "Ashbringer"
58
-  ,"Bloodfang"
59
-  ,"Dreadmist"
60
-  ,"Firemaw"
61
-  ,"Flamelash"
62
-  ,"Gandling"
63
-  ,"Gehennas"
64
-  ,"Golemagg"
65
-  ,"Hydraxian Waterlords"
66
-  ,"Judgement"
67
-  ,"Mirage Rach"
68
-  ,"Mograine"
69
-  ,"Nethergarde"
70
-  ,"Noggenfogg"
71
-  ,"Pyrewood Village"
72
-  ,"Razorgore"
73
-  ,"Shazzrah"
74
-  ,"Skullflame"
75
-  ,"Stonespine"
76
-  ,"Ten Storms"
77
-  ,"Zandalar Tribe"
78
-  ,"Amnennar"
79
-  ,"Auberdine"
80
-  ,"Finkle"
81
-  ,"Sulfuron"
82
-  ,"Everlook"
83
-  ,"Lucifron"
84
-  ,"Razorfen"
85
-  ,"Patchwerk"
86
-  ,"Venoxis"
87
-  ,"Dragon’s Call"
88
-  ,"Lakeshire"
89
-  ,"Transcendence"
74
+  , "Bloodfang"
75
+  , "Dreadmist"
76
+  , "Firemaw"
77
+  , "Flamelash"
78
+  , "Gandling"
79
+  , "Gehennas"
80
+  , "Golemagg"
81
+  , "Hydraxian Waterlords"
82
+  , "Judgement"
83
+  , "Mirage Rach"
84
+  , "Mograine"
85
+  , "Nethergarde"
86
+  , "Noggenfogg"
87
+  , "Pyrewood Village"
88
+  , "Razorgore"
89
+  , "Shazzrah"
90
+  , "Skullflame"
91
+  , "Stonespine"
92
+  , "Ten Storms"
93
+  , "Zandalar Tribe"
94
+  , "Amnennar"
95
+  , "Auberdine"
96
+  , "Finkle"
97
+  , "Sulfuron"
98
+  , "Everlook"
99
+  , "Lucifron"
100
+  , "Razorfen"
101
+  , "Patchwerk"
102
+  , "Venoxis"
103
+  , "Dragon’s Call"
104
+  , "Lakeshire"
105
+  , "Transcendence"
90
 ]
106
 ]

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

24
     boss1 = {}
24
     boss1 = {}
25
     gear1:string[] = []
25
     gear1:string[] = []
26
     
26
     
27
-    boss2= {}
27
+    boss2= {name: undefined, date:undefined}
28
     gear2:string[] = []
28
     gear2:string[] = []
29
 
29
 
30
     constructor(
30
     constructor(

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

10
 })
10
 })
11
 export class FrontcraftArchiveComponent implements OnInit{
11
 export class FrontcraftArchiveComponent implements OnInit{
12
 
12
 
13
+    manageRaid = false
13
     canSignup = false
14
     canSignup = false
14
     isSignedup = false
15
     isSignedup = false
15
     canManage = false
16
     canManage = false

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

1
 <div class="row">
1
 <div class="row">
2
     <div class="col-12 col-xl-6">
2
     <div class="col-12 col-xl-6">
3
-        <nb-card  [size]="giant">
3
+        <nb-card [size]="'giant'">
4
             <nb-card-body>
4
             <nb-card-body>
5
                 <nb-tabset>
5
                 <nb-tabset>
6
                     <nb-tab tabTitle="Info">
6
                     <nb-tab tabTitle="Info">

+ 4
- 16
test/backendTest.ts 查看文件

3
 import { T1, T2, Tiers } from "../src/backend/Types/Items";
3
 import { T1, T2, Tiers } from "../src/backend/Types/Items";
4
 
4
 
5
 import { RPCSocket } from "rpclibrary";
5
 import { RPCSocket } from "rpclibrary";
6
-import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, SRPriority, Spec, Signup } from "../src/backend/Types/Types";
6
+import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, 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
 
129
         return client.UserManager.createUser(user)
129
         return client.UserManager.createUser(user)
130
     }
130
     }
131
 
131
 
132
-    const login = async (name: string) : Promise<Auth> => {
133
-        const auth = await client.UserManager.login(name, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb')
134
-        
135
-        if(users[name]) users[name] = {
136
-            ...users[name],
137
-            auth: auth
138
-        }
139
-
140
-
141
-        return auth
142
-    }
143
-
144
     const createAccountAndUser = async (acc: protoAccount) => {
132
     const createAccountAndUser = async (acc: protoAccount) => {
145
         const account = await createAccount({
133
         const account = await createAccount({
146
             pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
134
             pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
573
         const user = Object.values(users)[0]
561
         const user = Object.values(users)[0]
574
         const itemname = "Maladath, Runed Blade of the Black Flight"
562
         const itemname = "Maladath, Runed Blade of the Black Flight"
575
         client.ItemManager.getItem(itemname).then(async item => {
563
         client.ItemManager.getItem(itemname).then(async item => {
576
-            await adminClient.softreserveCurrency.incrementCurrency(user.account, item.tier, 2)
577
-            const before = await client.ItemManager.getToken(user.character, item)
564
+            await adminClient.softreserveCurrency.incrementCurrency(user.account, item!.tier, 2)
565
+            const before = await client.ItemManager.getToken(user.character, item!)
578
 
566
 
579
             if (!before || before.level !== 4) {
567
             if (!before || before.level !== 4) {
580
                 console.log("expected level to be 4", before ? before.level : '?');
568
                 console.log("expected level to be 4", before ? before.level : '?');
690
             let streaks = await client.ItemManager.getTokens(user.character, [BWL0.tier], false)
678
             let streaks = await client.ItemManager.getTokens(user.character, [BWL0.tier], false)
691
             if (reserves!.length != 1
679
             if (reserves!.length != 1
692
                 || streaks!.length != 0
680
                 || streaks!.length != 0
693
-                || reserves![0].itemname !== T2_0.itemname
681
+                || reserves![0].itemname !== T2_0!.itemname
694
                 || reserves![0].level !== 1) {
682
                 || reserves![0].level !== 1) {
695
                 console.log("Bad Token status 1", reserves, streaks);
683
                 console.log("Bad Token status 1", reserves, streaks);
696
                 done(new Error("Bad Token status"))
684
                 done(new Error("Bad Token status"))

+ 3
- 4
tsconfig.json 查看文件

3
       "strictPropertyInitialization": false,
3
       "strictPropertyInitialization": false,
4
       "noImplicitAny": false,
4
       "noImplicitAny": false,
5
       "target": "ESnext",
5
       "target": "ESnext",
6
-      "module": "commonjs",
7
       "declaration": true,
6
       "declaration": true,
8
-      "outDir": "./lib",
9
       "strict": true,
7
       "strict": true,
10
       "experimentalDecorators": true,
8
       "experimentalDecorators": true,
11
       "emitDecoratorMetadata": true
9
       "emitDecoratorMetadata": true
12
     },
10
     },
13
-    "include": ["src/backend/**/*", "test/**/*"],
14
-    "exclude": ["node_modules", "**/__tests__/*"]
11
+    "angularCompilerOptions": {
12
+      "entryModule": "./src/backend/Admin/app.server.module#AppServerModule"
13
+    }
15
 }
14
 }

+ 14
- 0
tsconfig.server.json 查看文件

1
+{
2
+  "extends": "./tsconfig.json",
3
+  "compilerOptions": {
4
+    "outDir": "./lib",
5
+    "module": "commonjs",
6
+    "types": ["node"]
7
+  },
8
+  "include": ["src/backend/**/*", "test/**/*"],
9
+  "exclude": ["node_modules", "**/__tests__/*"],
10
+
11
+  "angularCompilerOptions": {
12
+    "entryModule": "./src/app/app.server.module#AppServerModule"
13
+  }
14
+}

Loading…
取消
儲存