Skip to content

Commit 874c0b5

Browse files
Merge branch 'master' of https://github.com/frc3223/stats
2 parents 632f300 + fed4467 commit 874c0b5

18 files changed

+623
-86
lines changed

package-lock.json

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ export class App {
9999
nav: false, title: "event", adminRoute: false,
100100
navigationStrategy: navToGameEventTeams
101101
},
102+
{
103+
route: ["year/:year/event/:eventCode/seed-predictions"],
104+
name: "seed-predictions",
105+
nav: false, title: "Seed Predictions", adminRoute: false,
106+
moduleId: PLATFORM.moduleName("event-matches/seed-predictions"),
107+
},
102108
{
103109
route: ["year/:year/event/:eventCode/team/:teamNumber"],
104110
name: "event-team",

src/custom-validation-rules.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { autoinject } from "aurelia-framework";
22
import { ValidationRules } from "aurelia-validation";
33
import { FrcStatsContext, EventMatchEntity, qualitativeAnswers, DeepSpaceGamepiece, allDeepSpaceLocations } from "./persistence";
44

5-
function isEmpty(z) {
5+
export function isEmpty(z) {
66
return z == null || z == "";
77
}
88

src/district-rankings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export class DistrictRankingsPage {
88
// engineering inspiration: 9
99
// rookie all star: 10
1010
public rankings: TeamRanking[];
11-
public districtKeys = ["2014pnw", "2015pnw", "2016pnw", "2017pnw", "2018pnw"];
11+
public districtKeys = ["2014pnw", "2015pnw", "2016pnw", "2017pnw", "2018pnw", "2019pnw"];
1212
public districtKey: string;
1313

1414
constructor(private api: TbaApi) {

src/event-matches/event-matches.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ <h1> ${event.name} * ${gameName} * ${event.calendarYear}</h1>
1313
<li class='nav-item'>
1414
<a class='nav-link' route-href="route: event-teams; params.bind: {year: event.year, eventCode: event.eventCode}">Teams (${teams.length})</a>
1515
</li>
16+
<li class='nav-item'>
17+
<a class='nav-link' route-href="route: seed-predictions; params.bind: {year: event.year, eventCode: event.eventCode}">
18+
Seed Predictions
19+
</a>
20+
</li>
1621
</ul>
1722
<div class='tab-content'>
1823
<table class="table table-hover">

src/event-matches/event-matches.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export class EventMatches {
9898
}
9999

100100
getEventMatches(){
101-
return this.dbContext.eventMatches.where(["year", "eventCode"]).equals([this.event.year, this.event.eventCode]).toArray().then(eventMatches => {
101+
return this.dbContext.getEventMatches(this.event.year, this.event.eventCode).then(eventMatches => {
102102
this.eventMatches = eventMatches;
103103
this.eventMatches.sort((a,b) => naturalSort(a.matchNumber, b.matchNumber));
104104
}).then(() => {
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<template>
2+
<require from="aurelia-bootstrap/tabs/aubs-tab"></require>
3+
<require from="aurelia-bootstrap/tabs/aubs-tabset"></require>
4+
<require from="aurelia-validation/validate-binding-behavior"></require>
5+
<require from="./seed-predictions.css"></require>
6+
7+
<div class='container-fluid'>
8+
<h1> ${event.name} * ${gameName} * ${event.calendarYear}</h1>
9+
10+
<!--<p> Maybe make a tab for match schedule, and make a tab for team list? </p>-->
11+
<ul class='nav nav-tabs'>
12+
<li class='nav-item'>
13+
<a class='nav-link'
14+
route-href="route: event-matches; params.bind: {year: event.year, eventCode: event.eventCode}">Matches</a>
15+
</li>
16+
<li class='nav-item'>
17+
<a class='nav-link'
18+
route-href="route: event-teams; params.bind: {year: event.year, eventCode: event.eventCode}">Teams
19+
(${teamsLength})</a>
20+
</li>
21+
<li class='nav-item'>
22+
<a class='nav-link active'
23+
route-href="route: seed-predictions; params.bind: {year: event.year, eventCode: event.eventCode}">
24+
Seed Predictions
25+
</a>
26+
</li>
27+
</ul>
28+
<div class='tab-content'>
29+
<h1>Win Predictions</h1>
30+
<div id='duhTable' role="table">
31+
<div class='table-head'>
32+
<div class='table-row'>
33+
<div>Match</div>
34+
<div>Win Prediction</div>
35+
<div>other RP, Red </div>
36+
<div>other RP, Blue </div>
37+
<div class='red'>Red 1</div>
38+
<div class='red'>Red 2</div>
39+
<div class='red'>Red 3</div>
40+
<div class='blue'>Blue 1</div>
41+
<div class='blue'>Blue 2</div>
42+
<div class='blue'>Blue 3</div>
43+
</div>
44+
</div>
45+
<div class='table-body'>
46+
<div class='table-row' repeat.for="match of eventMatches">
47+
<div> ${match.matchNumber}</div>
48+
<div class='form-group'>
49+
<select class='form-control' value.bind='match.winPrediction & validate:rules' change.delegate='calculateSeed()'>
50+
<option></option>
51+
<option repeat.for="opt of winOptions" value-bind="opt">${opt}</option>
52+
</select>
53+
</div>
54+
<div class='form-group'>
55+
<select class="form-control" value.bind='match.redRP & validate:rules' change.delegate='calculateSeed()'>
56+
<option></option>
57+
<option repeat.for="opt of rpOptions" model.bind="opt">${opt}</option>
58+
</select>
59+
</div>
60+
<div class='form-group'>
61+
<select class="form-control" value.bind='match.blueRP &validate:rules' change.delegate='calculateSeed()'>
62+
<option></option>
63+
<option repeat.for="opt of rpOptions" model.bind="opt">${opt}</option>
64+
</select>
65+
</div>
66+
<div class='red'>
67+
${match.red1}
68+
</div>
69+
<div class='red'>
70+
${match.red2}
71+
</div>
72+
<div class='red'>
73+
${match.red3}
74+
</div>
75+
<div class='blue'>
76+
${match.blue1}
77+
</div>
78+
<div class='blue'>
79+
${match.blue2}
80+
</div>
81+
<div class='blue'>
82+
${match.blue3}
83+
</div>
84+
</div>
85+
</div>
86+
</div>
87+
<div>
88+
<button class='btn btn-primary' click.delegate='save()'>Save</button>
89+
</div>
90+
<h1>Seed Prediction</h1>
91+
<div id='SeedTable' role="table">
92+
<div class='table-head'>
93+
<div class='table-row'>
94+
<div>Seed</div>
95+
<div>Team</div>
96+
<div>RP </div>
97+
</div>
98+
</div>
99+
<div class='table-body'>
100+
<div class='table-row' repeat.for="record of seedRecords">
101+
<div>${record.seed}</div>
102+
<div>${record.teamNumber}</div>
103+
<div>${record.RP}</div>
104+
105+
</div>
106+
107+
</div>
108+
</div>
109+
</div>
110+
</template>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#duhTable {
2+
display: grid;
3+
grid-template-columns: 70px 150px 120px 120px repeat(6, 70px);
4+
grid-column-gap: 10px;
5+
height: 500px;
6+
width: 1000px;
7+
overflow-y: auto;
8+
9+
}
10+
#SeedTable {
11+
display: grid;
12+
grid-template-columns: 120px 150px 150px;
13+
grid-column-gap: 10px;
14+
height: 500px;
15+
width: 1000px;
16+
overflow-y: auto;
17+
18+
}
19+
20+
.table-head, .table-row, .table-body {
21+
display: contents;
22+
23+
}
24+
25+
.table-head > .table-row > div {
26+
position: sticky;
27+
top: 0;
28+
background-color: white;
29+
30+
}
31+
.table-head > .table-row > div.red {
32+
background-color: #fee;
33+
}
34+
.table-head > .table-row > div.blue {
35+
background-color: #eef;
36+
}

src/event-matches/seed-predictions.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { autoinject } from "aurelia-framework";
2+
import * as naturalSort from "javascript-natural-sort";
3+
import { FrcStatsContext, EventEntity, EventMatchEntity, EventMatchSlots, WinPrediction } from "../persistence";
4+
import { gameManager } from "../games/index";
5+
import { ValidationControllerFactory, ValidationController, ValidationRules } from "aurelia-validation";
6+
import { BootstrapRenderer } from "../utilities/bootstrap-renderer";
7+
import { stringify } from "querystring";
8+
import { isEmpty } from "../custom-validation-rules";
9+
10+
@autoinject
11+
export class SeedPredictionsPage {
12+
gameName: string;
13+
event: EventEntity;
14+
eventMatches: EventMatchEntity[];
15+
seedRecords: TeamSeedRecord[];
16+
public validationController: ValidationController;
17+
public rules: any[];
18+
private renderer: BootstrapRenderer;
19+
public teamsLength: number;
20+
21+
winOptions : WinPrediction[] = ["Red", "Blue", "Tie"];
22+
rpOptions = [1, 2];
23+
24+
constructor(
25+
validationControllerFactory: ValidationControllerFactory,
26+
private dbContext: FrcStatsContext
27+
) {
28+
29+
this.validationController = validationControllerFactory.createForCurrentScope();
30+
this.seedRecords = [];
31+
32+
}
33+
34+
public async activate(params) {
35+
let game = gameManager.getGame(params.year);
36+
this.gameName = game.name;
37+
this.event = await this.dbContext.getEvent(params.year, params.eventCode);
38+
this.eventMatches = await this.dbContext.getEventMatches(this.event.year, this.event.eventCode);
39+
this.eventMatches.sort((a,b) => naturalSort(a.matchNumber, b.matchNumber));
40+
41+
this.setupValidation();
42+
this.calculateSeed();
43+
}
44+
45+
private setupValidation() {
46+
this.rules = ValidationRules
47+
.ensure((m: EventMatchEntity) => m.winPrediction)
48+
.required()
49+
.rules;
50+
51+
this.renderer = new BootstrapRenderer({ showMessages: true });
52+
this.validationController.addRenderer(this.renderer);
53+
54+
}
55+
56+
save() {
57+
this.dbContext.eventMatches.bulkPut(this.eventMatches);
58+
}
59+
60+
public calculateSeed() {
61+
let teams = new Map<string, TeamSeedRecord>();
62+
for(var eventMatch of this.eventMatches) {
63+
for(var slot of EventMatchSlots) {
64+
let teamNumber = eventMatch[slot.prop];
65+
if (!teams.has(teamNumber)) {
66+
teams.set(teamNumber, {
67+
teamNumber: teamNumber,
68+
seed: 0,
69+
RP: 0,
70+
});
71+
}
72+
let team = teams.get(teamNumber);
73+
let isBlue = slot.prop.startsWith("blue");
74+
let isRed = slot.prop.startsWith("red");
75+
76+
if(
77+
(eventMatch.winPrediction == "Blue" && isBlue) ||
78+
(eventMatch.winPrediction == "Red" && isRed)
79+
) {
80+
team.RP += 2;
81+
}else if(eventMatch.winPrediction == "Tie" ) {
82+
team.RP += 1;
83+
}
84+
85+
if(!isEmpty(eventMatch.redRP) && isRed) {
86+
team.RP += parseInt(<any>eventMatch.redRP);
87+
}
88+
89+
if(!isEmpty(eventMatch.blueRP) && isBlue) {
90+
team.RP += parseInt(<any>eventMatch.blueRP);
91+
}
92+
}
93+
}
94+
this.teamsLength = teams.size;
95+
96+
this.seedRecords = Array.from(teams.values());
97+
this.seedRecords.sort((a, b) => b.RP - a.RP);
98+
let i = 1;
99+
for(var rec of this.seedRecords) {
100+
rec.seed = i;
101+
i++;
102+
}
103+
}
104+
}
105+
106+
107+
interface TeamSeedRecord {
108+
teamNumber: string;
109+
seed: number;
110+
RP: number;
111+
}
112+

src/games/deepspace/bingo-entry.html

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<template>
2+
<ux-dialog>
3+
<ux-dialog-header>
4+
</ux-dialog-header>
5+
<ux-dialog-body>
6+
<div class='row'>
7+
<div class='col'>
8+
<label>Match</label>
9+
<select class='form-control' value.bind="entry.matchNumber">
10+
<option></option>
11+
<option repeat.for="matchNumber of matches" value.bind="matchNumber">${matchNumber}</option>
12+
</select>
13+
</div>
14+
</div>
15+
<div class='row'>
16+
<div class='col'>
17+
<label>Team</label>
18+
<select class='form-control' value.bind="entry.teamNumber">
19+
<option></option>
20+
<option repeat.for="teamNumber of teams" value.bind="teamNumber">${teamNumber}</option>
21+
</select>
22+
</div>
23+
</div>
24+
<div class='row'>
25+
<div class='col'>
26+
<label>Notes</label>
27+
<textarea class='form-control' value.bind="entry.notes"></textarea>
28+
</div>
29+
</div>
30+
</ux-dialog-body>
31+
<ux-dialog-footer>
32+
<button class="btn btn-primary" click.delegate="controller.ok()">
33+
Save
34+
</button>
35+
</ux-dialog-footer>
36+
</template>

0 commit comments

Comments
 (0)