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