Merge branch 'feature/statistic-charts' of hardi/opt-cc into master
						commit
						e8f8936b5e
					
				|  | @ -24,6 +24,18 @@ const WarSchema = new Schema({ | |||
|     set: v => Math.round(v), | ||||
|     required: true | ||||
|   }, | ||||
|   playersBlufor: { | ||||
|     type: Number, | ||||
|     get: v => Math.round(v), | ||||
|     set: v => Math.round(v), | ||||
|     default: 0 | ||||
|   }, | ||||
|   playersOpfor: { | ||||
|     type: Number, | ||||
|     get: v => Math.round(v), | ||||
|     set: v => Math.round(v), | ||||
|     default: 0 | ||||
|   }, | ||||
|   bestPlayerId: { | ||||
|     type: mongoose.Schema.Types.ObjectId, | ||||
|     ref: 'Player', | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -51,11 +51,11 @@ wars.route('/') | |||
|     const war = new WarModel(body); | ||||
| 
 | ||||
|     if (req.file) { | ||||
|       war.save((err, item) => { | ||||
|       war.save((err, war) => { | ||||
|         if (err) { | ||||
|           return next(err); | ||||
|         } | ||||
|         const folderName = __dirname + '/../resource/logs/' + item._id; | ||||
|         const folderName = __dirname + '/../resource/logs/' + war._id; | ||||
|         mkdirp(folderName, function (err) { | ||||
|           if (err) { | ||||
|             return next(err); | ||||
|  | @ -65,7 +65,7 @@ wars.route('/') | |||
|               return next(err); | ||||
|             } | ||||
|             //TODO: combine run and clean in one script, so log file gets touched only once
 | ||||
|             exec(__dirname + '/../war-parser/run.sh ' + folderName + ' ' + item._id, (error, stdout) => { | ||||
|             exec(__dirname + '/../war-parser/run.sh ' + folderName + ' ' + war._id, (error, stdout) => { | ||||
|               if (error) { | ||||
|                 return next(error); | ||||
|               } | ||||
|  | @ -74,14 +74,33 @@ wars.route('/') | |||
|                   return next(error); | ||||
|                 } | ||||
|                 let obj = JSON.parse(`${stdout}`); | ||||
|                 PlayerModel.create(obj, function (err) { | ||||
|                   if (err) { | ||||
|                     return next(err); | ||||
|                 for (let i = 0; i < obj.length; i++) { | ||||
|                   if (obj[i].fraction === 'BLUFOR') { | ||||
|                     war.playersBlufor++; | ||||
|                   } else { | ||||
|                     war.playersOpfor++; | ||||
|                   } | ||||
|                   res.status(codes.created); | ||||
|                   res.locals.items = item; | ||||
|                   return next(); | ||||
|                 }); | ||||
|                 } | ||||
| 
 | ||||
|                 WarModel.findByIdAndUpdate(war._id, war, {new: true}, (err, item) => { | ||||
|                   if (err) { | ||||
|                     err.status = codes.wrongrequest; | ||||
|                   } | ||||
|                   else if (!item) { | ||||
|                     err = new Error("item not found"); | ||||
|                     err.status = codes.notfound; | ||||
|                   } | ||||
|                   else { | ||||
|                     PlayerModel.create(obj, function (err) { | ||||
|                       if (err) { | ||||
|                         return next(err); | ||||
|                       } | ||||
|                       res.status(codes.created); | ||||
|                       res.locals.items = war; | ||||
|                       return next(); | ||||
|                     }); | ||||
|                   } | ||||
|                 }) | ||||
|               }); | ||||
|             }); | ||||
|           }); | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -11,19 +11,22 @@ | |||
|     "e2e": "ng e2e --serve=false" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@angular/cli": "1.0.5", | ||||
|     "@angular/common": "^4.1.1", | ||||
|     "@angular/compiler": "^4.1.1", | ||||
|     "@angular/compiler-cli": "^4.1.1", | ||||
|     "@angular/core": "^4.1.1", | ||||
|     "@angular/forms": "^4.1.1", | ||||
|     "@angular/http": "^4.1.1", | ||||
|     "@angular/platform-browser": "^4.1.1", | ||||
|     "@angular/platform-browser-dynamic": "^4.1.1", | ||||
|     "@angular/router": "^4.1.1", | ||||
|     "@angular/animations": "^4.3.2", | ||||
|     "@angular/cli": "^1.2.6", | ||||
|     "@angular/common": "^4.3.2", | ||||
|     "@angular/compiler": "^4.3.2", | ||||
|     "@angular/compiler-cli": "^4.3.2", | ||||
|     "@angular/core": "^4.3.2", | ||||
|     "@angular/forms": "^4.3.2", | ||||
|     "@angular/http": "^4.3.2", | ||||
|     "@angular/platform-browser": "^4.3.2", | ||||
|     "@angular/platform-browser-dynamic": "^4.3.2", | ||||
|     "@angular/router": "^4.3.2", | ||||
|     "@swimlane/ngx-charts": "^6.0.1", | ||||
|     "angular2-datatable": "^0.6.0", | ||||
|     "bootstrap": "^3.3.7", | ||||
|     "core-js": "^2.4.1", | ||||
|     "d3": "^4.10.0", | ||||
|     "jquery": "^3.1.0", | ||||
|     "jquery-ui": "^1.12.0", | ||||
|     "jquery-ui-bundle": "^1.11.4", | ||||
|  | @ -31,6 +34,7 @@ | |||
|     "rxjs": "^5.2.0", | ||||
|     "ts-helpers": "^1.1.1", | ||||
|     "typescript": "^2.3.2", | ||||
|     "webpack": "^3.4.1", | ||||
|     "zone.js": "^0.8.5" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|  |  | |||
|  | @ -24,13 +24,16 @@ | |||
|           <li class="dropdown"> | ||||
|             <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" | ||||
|                aria-expanded="false"> | ||||
|               Schlacht Statistik | ||||
|               Statistik | ||||
|               <span class="caret"></span> | ||||
|             </a> | ||||
|             <ul class="dropdown-menu scrollable-menu"> | ||||
|               <li *ngIf="loginService.hasPermission(3)"> | ||||
|                 <a routerLink='/cc-wars' class="link">Hinzufügen...</a> | ||||
|               </li> | ||||
|               <li> | ||||
|                 <a routerLink='/cc-statistic' class="link">Übersicht</a> | ||||
|               </li> | ||||
|               <li *ngFor="let war of wars"> | ||||
|                 <a [routerLink]="['/cc-wars/' + war._id]">{{war.title}} | ||||
|                   <small>{{war.date | date: 'dd.MM.yy'}}</small> | ||||
|  |  | |||
|  | @ -33,9 +33,12 @@ import {PromotionService} from "./services/promotion-service/promotion.service"; | |||
| import {FilterRankPipe} from "./filter/filter.pipe"; | ||||
| import {WarService} from "./services/war-service/war.service"; | ||||
| import {DataTableModule} from "angular2-datatable"; | ||||
| import {NgxChartsModule} from "@swimlane/ngx-charts"; | ||||
| import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; | ||||
| 
 | ||||
| @NgModule({ | ||||
|   imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule, ClipboardModule, DataTableModule], | ||||
|   imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule, ClipboardModule, DataTableModule, | ||||
|     BrowserAnimationsModule, NgxChartsModule], | ||||
|   providers: [ | ||||
|     HttpClient, | ||||
|     LoginService, | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ import {RequestPromotionComponent} from "./request/promotion/req-promotion.compo | |||
| import {ConfirmPromotionComponent} from "./request/confirm-promotion/confirm-promotion.component"; | ||||
| import {ConfirmAwardComponent} from "./request/confirm-award/confirm-award.component"; | ||||
| import {warRoutes, warsRoutingComponents} from "./wars/wars.routing"; | ||||
| import {StatisticComponent} from "./statistic/statistic.component"; | ||||
| 
 | ||||
| 
 | ||||
| export const appRoutes: Routes = [ | ||||
|  | @ -22,6 +23,7 @@ export const appRoutes: Routes = [ | |||
|   {path: '', redirectTo: '/cc-overview', pathMatch: 'full'}, | ||||
| 
 | ||||
|   {path: 'cc-wars', children: warRoutes}, | ||||
|   {path: 'cc-statistic', component: StatisticComponent}, | ||||
| 
 | ||||
|   {path: 'login', component: LoginComponent}, | ||||
|   {path: 'signup', component: SignupComponent}, | ||||
|  | @ -46,7 +48,7 @@ export const appRoutes: Routes = [ | |||
| export const appRouting = RouterModule.forRoot(appRoutes); | ||||
| 
 | ||||
| export const routingComponents = [LoginComponent, SignupComponent, RequestAwardComponent, RequestPromotionComponent, ConfirmAwardComponent, | ||||
|   ConfirmPromotionComponent, AdminComponent, ...armyRoutingComponents, NotFoundComponent, ...usersRoutingComponents, | ||||
|   ConfirmPromotionComponent, StatisticComponent, AdminComponent, ...armyRoutingComponents, NotFoundComponent, ...usersRoutingComponents, | ||||
|   ...squadsRoutingComponents, ...decorationsRoutingComponents, ...ranksRoutingComponents, ...warsRoutingComponents]; | ||||
| 
 | ||||
| export const routingProviders = [LoginGuardSQL, LoginGuardHL, LoginGuardMT, LoginGuardAdmin]; | ||||
|  |  | |||
|  | @ -0,0 +1,9 @@ | |||
| h3 { | ||||
|   width: 920px; | ||||
|   margin-left: 25%; | ||||
| } | ||||
| 
 | ||||
| .chart-container { | ||||
|   width: 1200px; | ||||
|   margin-left: 25%; | ||||
| } | ||||
|  | @ -0,0 +1,45 @@ | |||
| <h3>Punkte</h3> | ||||
| 
 | ||||
| <div class="chart-container"> | ||||
| 
 | ||||
|   <ngx-charts-line-chart | ||||
|     [view]="[1050, 400]" | ||||
|     [scheme]="colorScheme" | ||||
|     [results]="playerData" | ||||
|     [gradient]="false" | ||||
|     [xAxis]="true" | ||||
|     [yAxis]="true" | ||||
|     [legend]="true" | ||||
|     [legendTitle]="''" | ||||
|     [showXAxisLabel]="true" | ||||
|     [showYAxisLabel]="true" | ||||
|     [xAxisLabel]="'Schlachtdatum'" | ||||
|     [yAxisLabel]="'Punkte'" | ||||
|     [autoScale]="false" | ||||
|     (select)="onSelect($event)"> | ||||
|   </ngx-charts-line-chart> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
| <h3 style="margin-top: 370px;">Spielerzahlen</h3> | ||||
| 
 | ||||
| <div class="chart-container"> | ||||
| 
 | ||||
|   <ngx-charts-line-chart | ||||
|     [view]="[1050, 350]" | ||||
|     [scheme]="colorScheme" | ||||
|     [results]="pointData" | ||||
|     [gradient]="false" | ||||
|     [xAxis]="true" | ||||
|     [yAxis]="true" | ||||
|     [legend]="true" | ||||
|     [legendTitle]="''" | ||||
|     [showXAxisLabel]="true" | ||||
|     [showYAxisLabel]="true" | ||||
|     [xAxisLabel]="'Schlachtdatum'" | ||||
|     [yAxisLabel]="'Anzahl Spieler'" | ||||
|     [autoScale]="true" | ||||
|     (select)="onSelect($event)"> | ||||
|   </ngx-charts-line-chart> | ||||
| 
 | ||||
| </div> | ||||
|  | @ -0,0 +1,92 @@ | |||
| import {Component} from "@angular/core"; | ||||
| import {AppComponent} from "../app.component"; | ||||
| import {WarService} from "../services/war-service/war.service"; | ||||
| 
 | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'statistic', | ||||
|   templateUrl: './statistic.component.html', | ||||
|   styleUrls: ['./statistic.component.css'] | ||||
| }) | ||||
| export class StatisticComponent { | ||||
| 
 | ||||
|   pointData: any[] = []; | ||||
|   playerData: any[] = []; | ||||
| 
 | ||||
|   colorScheme = { | ||||
|     domain: ['#0000FF', '#B22222'] | ||||
|   }; | ||||
| 
 | ||||
|   constructor(private appComponent: AppComponent, | ||||
|               private warService: WarService) { | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit() { | ||||
|     let wars = this.appComponent.wars; | ||||
|     if (wars.length === 0) { | ||||
|       this.warService.getAllWars().subscribe(items => { | ||||
|         this.initChart(items); | ||||
|       }) | ||||
|     } | ||||
|     this.initChart(wars); | ||||
|   } | ||||
| 
 | ||||
|   initChart(wars: any[]) { | ||||
|     let pointsObj = [ | ||||
|       { | ||||
|         "name": "NATO", | ||||
|         "series": [] | ||||
|       }, | ||||
|       { | ||||
|         "name": "CSAT", | ||||
|         "series": [] | ||||
|       }]; | ||||
|     let playersObj = [ | ||||
|       { | ||||
|         "name": "NATO", | ||||
|         "series": [] | ||||
|       }, | ||||
|       { | ||||
|         "name": "CSAT", | ||||
|         "series": [] | ||||
|       } | ||||
|     ]; | ||||
|     for (let i = wars.length - 1; i >= 0; i--) { | ||||
|       const isoDate = wars[i].date.slice(0, 10); | ||||
|       const dayDate = parseInt(isoDate.slice(8, 10)) + 1; | ||||
|       const warDateString = (dayDate < 10 ? "0" + dayDate : dayDate) + '.' | ||||
|         + isoDate.slice(5, 7) + '.' + isoDate.slice(0, 4); | ||||
| 
 | ||||
|       const bluforData = { | ||||
|         name: warDateString, | ||||
|         value: wars[i].ptBlufor | ||||
|       }; | ||||
|       const opforData = { | ||||
|         name: warDateString, | ||||
|         value: wars[i].ptOpfor | ||||
|       }; | ||||
|       const bluforPlayers = { | ||||
|         name: warDateString, | ||||
|         value: wars[i].playersBlufor | ||||
|       }; | ||||
|       const opforPlayers = { | ||||
|         name: warDateString, | ||||
|         value: wars[i].playersOpfor | ||||
|       }; | ||||
| 
 | ||||
|       playersObj[0].series.push(bluforData); | ||||
|       playersObj[1].series.push(opforData); | ||||
|       pointsObj[0].series.push(bluforPlayers); | ||||
|       pointsObj[1].series.push(opforPlayers); | ||||
|     } | ||||
| 
 | ||||
|     this.pointData = pointsObj; | ||||
|     this.playerData = playersObj; | ||||
|     Object.assign(this, [this.playerData, this.pointData]) | ||||
|   } | ||||
| 
 | ||||
|   onSelect(event) { | ||||
|     console.log(event); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -55,7 +55,7 @@ export class WarSubmitComponent { | |||
|             this.router.navigate([war._id], {relativeTo: this.route}); | ||||
|           }, | ||||
|           error => { | ||||
|             this.error = error._body; | ||||
|             this.error = error._body.error.message; | ||||
|             this.showErrorLabel = true; | ||||
|             this.loading = false; | ||||
|           }); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue