Compare commits
19 Commits
d0df6e3e5c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
8d6129590a
|
|||
|
13aa2c29b0
|
|||
|
5f256e1983
|
|||
|
4dbc6a2a4d
|
|||
|
e26cd21cc6
|
|||
|
139fb20814
|
|||
|
1027011447
|
|||
|
b09b683727
|
|||
|
aec84dca5d
|
|||
|
7082abcdf7
|
|||
|
7c3404acb0
|
|||
|
e8165727de
|
|||
|
6d2c750a58
|
|||
|
7f436ae0b8
|
|||
|
753e490c29
|
|||
|
051657ef65
|
|||
|
e41a07411e
|
|||
|
cd5154a07a
|
|||
|
ae45cc78a1
|
@@ -26,36 +26,49 @@
|
||||
<div id="player-card-scores" class="visible-{{this.currentPage === 3}}">
|
||||
<p>Please enter the points that every player has collected:</p>
|
||||
<table class="point-entry">
|
||||
<tr>
|
||||
<tr *ngIf="this.actualPlayers[0]">
|
||||
<td><p>{{this.actualPlayers[0].firstName}}</p></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[0].finalCardScore"/></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[0].finalCardScore" (change)="this.calculateCurrentScores()"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr *ngIf="this.actualPlayers[1]">
|
||||
<td><p>{{this.actualPlayers[1].firstName}}</p></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[1].finalCardScore"/></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[1].finalCardScore" (change)="this.calculateCurrentScores()"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr *ngIf="this.actualPlayers[2]">
|
||||
<td><p>{{this.actualPlayers[2].firstName}}</p></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[2].finalCardScore"/></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[2].finalCardScore" (change)="this.calculateCurrentScores()"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr *ngIf="this.actualPlayers[3]">
|
||||
<td><p>{{this.actualPlayers[3].firstName}}</p></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[3].finalCardScore"/></td>
|
||||
<td><input type="number" [(ngModel)]="this.actualPlayers[3].finalCardScore" (change)="this.calculateCurrentScores()"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p id="score-warn" *ngIf="!totalScoreValid()">Total score doesn't add up!</p>
|
||||
<button (click)="switchToNextPage()" [disabled]="!totalScoreValid()">Next</button>
|
||||
<p id="score-warn" *ngIf="calculatePointSum() !== 240">Total score doesn't add up ({{getScoreDifferenceText()}})</p>
|
||||
<button (click)="switchToNextPage()" [disabled]="!calculatePointSum()">Next</button>
|
||||
</div>
|
||||
<div id="which-solo" class="visible-{{this.currentPage === 4}}">
|
||||
|
||||
<p>Select the Solo that has been played:</p>
|
||||
<div class="togglebtn active-{{isSoloActive(solo)}}" *ngFor="let solo of getAllPossibleSolos()" (click)="toggleSolo(solo)">{{solo.toString()}}</div>
|
||||
<p id="solo-warn" *ngIf="noSoloSelectedYet()">Please select a solo to continue</p>
|
||||
<button (click)="switchToNextPage()" [disabled]="noSoloSelectedYet()">Next</button>
|
||||
</div>
|
||||
<div id="extra-points" class="visible-{{this.currentPage === 5}}">
|
||||
|
||||
<p>Extra Points</p>
|
||||
<div *ngFor="let player of actualPlayers">
|
||||
<p>{{player.firstName}}</p>
|
||||
<input type="number" [(ngModel)]="player.foxesCaught" (change)="this.calculateCurrentScores()"/>
|
||||
</div>
|
||||
<p id="foxes-warn" *ngIf="!checkTotalFoxPoints()">Please check the number of caught foxes!</p>
|
||||
<button (click)="switchToNextPage()" [disabled]="!checkAllExtraPoints()">Next</button>
|
||||
</div>
|
||||
<div id="summary" class="visible-{{this.currentPage === 6}}">
|
||||
<p>Game Summary</p>
|
||||
<button (click)="saveGame()">Save Game</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="scores">
|
||||
<p class="team-{{player.team}}" *ngFor="let player of actualPlayers">
|
||||
{{player.firstName}}: {{calculateCurrentScore(player)}}
|
||||
{{player.firstName}}: {{player.gamePoints}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
color: $inactive;
|
||||
}
|
||||
|
||||
#player-amount-warn, #announcement-warn, #team-warn, #score-warn {
|
||||
#player-amount-warn, #announcement-warn, #team-warn, #score-warn, #solo-warn {
|
||||
color: $warn;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AddGameComponent } from './add-game.component';
|
||||
import {Team} from '../../models/doppelkopf/enums/team';
|
||||
|
||||
describe('AddGameComponent', () => {
|
||||
let component: AddGameComponent;
|
||||
@@ -20,4 +21,49 @@ describe('AddGameComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have the correct score for a normal game', () => {
|
||||
// Set up testing data
|
||||
component.actualPlayers = [
|
||||
{
|
||||
firebonkId: 1,
|
||||
uuid: 'abc-def-ghi-j',
|
||||
firstName: 'Patrick',
|
||||
team: Team.RE,
|
||||
gamePoints: 0,
|
||||
finalCardScore: 123,
|
||||
},
|
||||
{
|
||||
firebonkId: 1,
|
||||
uuid: 'abc-def-ghi-k',
|
||||
firstName: 'Julian',
|
||||
team: Team.RE,
|
||||
gamePoints: 17,
|
||||
finalCardScore: 0,
|
||||
},
|
||||
{
|
||||
firebonkId: 1,
|
||||
uuid: 'abc-def-ghi-l',
|
||||
firstName: 'Yanick',
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 50,
|
||||
finalCardScore: 0,
|
||||
},
|
||||
{
|
||||
firebonkId: 1,
|
||||
uuid: 'abc-def-ghi-m',
|
||||
firstName: 'Janina',
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 50,
|
||||
finalCardScore: 0,
|
||||
},
|
||||
]
|
||||
|
||||
component.calculateCurrentScores();
|
||||
|
||||
expect(component.actualPlayers[0].gamePoints).toEqual(1);
|
||||
expect(component.actualPlayers[1].gamePoints).toEqual(1);
|
||||
expect(component.actualPlayers[2].gamePoints).toEqual(-1);
|
||||
expect(component.actualPlayers[3].gamePoints).toEqual(-1);
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {Player} from '../../models/doppelkopf/player';
|
||||
import * as Announcement from '../../models/doppelkopf/enums/announcement';
|
||||
import * as announcements from '../../models/doppelkopf/enums/announcement';
|
||||
import * as solos from '../../models/doppelkopf/enums/solo';
|
||||
import {Team} from '../../models/doppelkopf/enums/team';
|
||||
|
||||
@Component({
|
||||
@@ -12,7 +13,8 @@ export class AddGameComponent implements OnInit {
|
||||
potentialPlayers: Player[] = [];
|
||||
actualPlayers: Player[] = [];
|
||||
|
||||
selectedAnnouncements: Announcement.Announcement[] = [];
|
||||
selectedAnnouncements: announcements.Announcement[] = [];
|
||||
soloPlayed?: solos.Solo;
|
||||
|
||||
currentPage: number = 0;
|
||||
|
||||
@@ -31,31 +33,43 @@ export class AddGameComponent implements OnInit {
|
||||
firebonkId: 1,
|
||||
uuid: 'abc-def-ghi-j',
|
||||
firstName: 'Patrick',
|
||||
team: Team.CONTRA
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 0,
|
||||
finalCardScore: 0,
|
||||
// foxesCaught: 1,
|
||||
// wonLastTrickWithCharlie: true
|
||||
});
|
||||
this.potentialPlayers.push({
|
||||
firebonkId: 2,
|
||||
uuid: 'abc-def-ghi-k',
|
||||
firstName: 'Julian',
|
||||
team: Team.CONTRA
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 0,
|
||||
finalCardScore: 0
|
||||
});
|
||||
this.potentialPlayers.push({
|
||||
firebonkId: 3,
|
||||
uuid: 'abc-def-ghi-l',
|
||||
firstName: 'Yannick',
|
||||
team: Team.CONTRA
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 0,
|
||||
finalCardScore: 0
|
||||
});
|
||||
this.potentialPlayers.push({
|
||||
firebonkId: 4,
|
||||
uuid: 'abc-def-ghi-m',
|
||||
firstName: 'Janina',
|
||||
team: Team.CONTRA
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 0,
|
||||
finalCardScore: 0
|
||||
});
|
||||
this.potentialPlayers.push({
|
||||
firebonkId: 5,
|
||||
uuid: 'abc-def-ghi-n',
|
||||
firstName: 'Moritz',
|
||||
team: Team.CONTRA
|
||||
team: Team.CONTRA,
|
||||
gamePoints: 0,
|
||||
finalCardScore: 0
|
||||
});
|
||||
|
||||
this.actualPlayers.push(...this.potentialPlayers.slice(0, 4));
|
||||
@@ -65,6 +79,15 @@ export class AddGameComponent implements OnInit {
|
||||
* Switches the entry mask UI to the next page
|
||||
*/
|
||||
switchToNextPage(): void {
|
||||
if (this.currentPage >= 4) {
|
||||
this.calculateCurrentScores();
|
||||
}
|
||||
|
||||
if(this.currentPage === 3 && !this.checkIfSolo()) {
|
||||
// If we don't play a solo, we can skip the solo page
|
||||
this.currentPage++;
|
||||
}
|
||||
|
||||
this.currentPage++;
|
||||
}
|
||||
|
||||
@@ -127,15 +150,116 @@ export class AddGameComponent implements OnInit {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Toggles the activity status for the given announcement
|
||||
* Toggles the activity status for the given announcement and also activates / deactivates other announcements
|
||||
* to conform to the rules.
|
||||
* @param announcement The announcement to toggle activity for
|
||||
*/
|
||||
toggleAnnouncement(announcement: Announcement.Announcement): void {
|
||||
toggleAnnouncement(announcement: announcements.Announcement): void {
|
||||
let index = this.selectedAnnouncements.indexOf(announcement);
|
||||
if (index !== -1) {
|
||||
this.selectedAnnouncements.splice(index, 1);
|
||||
this.deactivateLowerAnnouncements(announcement);
|
||||
} else {
|
||||
this.selectedAnnouncements.push(announcement);
|
||||
this.activateHigherAnnouncements(announcement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates all lower announcements. E.g.: When RE is deactivated, RE_NO_NINETY and all lower also get deactivated
|
||||
* @param announcement The announcement that has been deactivated
|
||||
*/
|
||||
deactivateLowerAnnouncements(announcement: announcements.Announcement) {
|
||||
// First for RE
|
||||
switch (announcement) {
|
||||
case announcements.Announcement.RE:
|
||||
this.deactivateAnnouncement(announcements.Announcement.RE_NO_NINETY);
|
||||
this.deactivateAnnouncement(announcements.Announcement.RE_NO_SIXTY);
|
||||
this.deactivateAnnouncement(announcements.Announcement.RE_NO_THIRTY);
|
||||
break;
|
||||
case announcements.Announcement.RE_NO_NINETY:
|
||||
this.deactivateAnnouncement(announcements.Announcement.RE_NO_SIXTY);
|
||||
this.deactivateAnnouncement(announcements.Announcement.RE_NO_THIRTY);
|
||||
break;
|
||||
case announcements.Announcement.RE_NO_SIXTY:
|
||||
this.deactivateAnnouncement(announcements.Announcement.RE_NO_THIRTY);
|
||||
break;
|
||||
}
|
||||
|
||||
// Now for CONTRA
|
||||
switch (announcement) {
|
||||
case announcements.Announcement.CONTRA:
|
||||
this.deactivateAnnouncement(announcements.Announcement.CONTRA_NO_NINETY);
|
||||
this.deactivateAnnouncement(announcements.Announcement.CONTRA_NO_SIXTY);
|
||||
this.deactivateAnnouncement(announcements.Announcement.CONTRA_NO_THIRTY);
|
||||
break;
|
||||
case announcements.Announcement.CONTRA_NO_NINETY:
|
||||
this.deactivateAnnouncement(announcements.Announcement.CONTRA_NO_SIXTY);
|
||||
this.deactivateAnnouncement(announcements.Announcement.CONTRA_NO_THIRTY);
|
||||
break;
|
||||
case announcements.Announcement.CONTRA_NO_SIXTY:
|
||||
this.deactivateAnnouncement(announcements.Announcement.CONTRA_NO_THIRTY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the given announcement if it is active
|
||||
* @param announcement The announcement to deactivate
|
||||
*/
|
||||
deactivateAnnouncement(announcement: announcements.Announcement) {
|
||||
let index = this.selectedAnnouncements.indexOf(announcement);
|
||||
if (index !== -1) {
|
||||
this.selectedAnnouncements.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates all higher announcements. E.g.: When RE_NO_NINETY is activated, RE also gets activated
|
||||
* @param announcement The announcement that has been activated
|
||||
*/
|
||||
activateHigherAnnouncements(announcement: announcements.Announcement) {
|
||||
// First for RE
|
||||
switch (announcement) {
|
||||
case announcements.Announcement.RE_NO_THIRTY:
|
||||
this.activateAnnouncement(announcements.Announcement.RE_NO_SIXTY);
|
||||
this.activateAnnouncement(announcements.Announcement.RE_NO_NINETY);
|
||||
this.activateAnnouncement(announcements.Announcement.RE);
|
||||
break;
|
||||
case announcements.Announcement.RE_NO_SIXTY:
|
||||
this.activateAnnouncement(announcements.Announcement.RE_NO_NINETY);
|
||||
this.activateAnnouncement(announcements.Announcement.RE);
|
||||
break;
|
||||
case announcements.Announcement.RE_NO_NINETY:
|
||||
this.activateAnnouncement(announcements.Announcement.RE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Now for CONTRA
|
||||
switch (announcement) {
|
||||
case announcements.Announcement.CONTRA_NO_THIRTY:
|
||||
this.activateAnnouncement(announcements.Announcement.CONTRA_NO_SIXTY);
|
||||
this.activateAnnouncement(announcements.Announcement.CONTRA_NO_NINETY);
|
||||
this.activateAnnouncement(announcements.Announcement.CONTRA);
|
||||
break;
|
||||
case announcements.Announcement.CONTRA_NO_SIXTY:
|
||||
this.activateAnnouncement(announcements.Announcement.CONTRA_NO_NINETY);
|
||||
this.activateAnnouncement(announcements.Announcement.CONTRA);
|
||||
break;
|
||||
case announcements.Announcement.CONTRA_NO_NINETY:
|
||||
this.activateAnnouncement(announcements.Announcement.CONTRA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the given announcement if it is inactive
|
||||
* @param announcement The announcement to activate
|
||||
*/
|
||||
activateAnnouncement(announcement: announcements.Announcement) {
|
||||
let index = this.selectedAnnouncements.indexOf(announcement);
|
||||
if (index === -1) {
|
||||
this.selectedAnnouncements.push(announcement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,26 +267,38 @@ export class AddGameComponent implements OnInit {
|
||||
* Checks if the given announcement is already marked as selected
|
||||
* @param announcement The announcement to check the status for
|
||||
*/
|
||||
isAnnouncementActive(announcement: Announcement.Announcement): boolean {
|
||||
isAnnouncementActive(announcement: announcements.Announcement): boolean {
|
||||
return this.selectedAnnouncements.indexOf(announcement) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all possible announcements
|
||||
*/
|
||||
getAllPossibleAnnouncements(): Announcement.Announcement[] {
|
||||
return Announcement.getAllAnnouncementValues();
|
||||
getAllPossibleAnnouncements(): announcements.Announcement[] {
|
||||
return announcements.getAllAnnouncementValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, if the currently selected announcements are a valid set of announcements
|
||||
*/
|
||||
checkAnnouncementsValid(): boolean {
|
||||
return Announcement.checkValidity(this.selectedAnnouncements);
|
||||
return announcements.checkValidity(this.selectedAnnouncements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the two highest announcements for this game (one for RE, one for CONTRA, if applicable)
|
||||
*/
|
||||
getHighestAnnouncements(): string {
|
||||
return Announcement.returnTwoHighestAnnouncements(this.selectedAnnouncements);
|
||||
return announcements.returnTwoHighestAnnouncements(this.selectedAnnouncements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given announcement has been selected
|
||||
* @param announcement The announcement to check
|
||||
*/
|
||||
checkAnnouncementActive(announcement: announcements.Announcement): boolean {
|
||||
let index = this.selectedAnnouncements.indexOf(announcement);
|
||||
return index !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,13 +354,27 @@ export class AddGameComponent implements OnInit {
|
||||
/**
|
||||
* Checks if the sum of all points is exactly 240
|
||||
*/
|
||||
totalScoreValid(): boolean {
|
||||
calculatePointSum(): number {
|
||||
let totalScore: number = 0;
|
||||
for (let player of this.actualPlayers) {
|
||||
totalScore += player.finalCardScore ?? 0;
|
||||
}
|
||||
|
||||
return totalScore === 240;
|
||||
return totalScore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string that explains if the total point sum is too low / too high
|
||||
*/
|
||||
getScoreDifferenceText(): string {
|
||||
let difference = this.calculatePointSum() - 240;
|
||||
|
||||
if (difference > 0) {
|
||||
return difference + ' more than expected';
|
||||
} else {
|
||||
difference *= -1;
|
||||
return difference + ' less than expected';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,33 +386,88 @@ export class AddGameComponent implements OnInit {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculates the game points for the given player
|
||||
* @param player The player to calculate points for
|
||||
* Calculates the game points for all players
|
||||
*/
|
||||
calculateCurrentScore(player: Player): number {
|
||||
calculateCurrentScores(): void {
|
||||
let gameScore: number = 0;
|
||||
let teamScore = this.getTeamScore(player);
|
||||
|
||||
// Won? If so, by how much?
|
||||
if (teamScore > 210) {
|
||||
gameScore += 4;
|
||||
} else if (teamScore > 180) {
|
||||
gameScore += 3;
|
||||
} else if (teamScore > 150) {
|
||||
gameScore += 2;
|
||||
} else if (teamScore > 120) {
|
||||
gameScore += 1;
|
||||
} else if (teamScore < 30) {
|
||||
gameScore -= 4;
|
||||
} else if (teamScore < 60) {
|
||||
gameScore -= 3;
|
||||
} else if (teamScore < 90) {
|
||||
gameScore -= 2;
|
||||
let winningTeam = this.getWinningTeamAndScore().team;
|
||||
let winningTeamScore = this.getWinningTeamAndScore().score;
|
||||
let unfulfilledAnnouncementPoints = this.checkUnfulfilledAnnouncements(winningTeam, winningTeamScore);
|
||||
let isSoloPlay = this.checkIfSolo();
|
||||
|
||||
// We are going to calculate the points for the winning team and then set all players points accordingly
|
||||
|
||||
if (unfulfilledAnnouncementPoints === 0) {
|
||||
gameScore += this.calculateNormalScore(winningTeamScore, winningTeam);
|
||||
} else {
|
||||
gameScore -= 1;
|
||||
gameScore += unfulfilledAnnouncementPoints;
|
||||
winningTeam = winningTeam === Team.RE ? Team.CONTRA : Team.RE;
|
||||
}
|
||||
|
||||
// TODO Announcements etc
|
||||
if(winningTeam === Team.CONTRA) {
|
||||
// Against the elders
|
||||
gameScore++;
|
||||
}
|
||||
|
||||
// Double Score in case of announcement
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE)) {
|
||||
gameScore *= 2;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA)) {
|
||||
gameScore *= 2;
|
||||
}
|
||||
|
||||
// Bonus points
|
||||
if (!isSoloPlay) {
|
||||
gameScore += this.getFinalFoxPoints(winningTeam);
|
||||
gameScore += this.getCharliePoints(winningTeam);
|
||||
}
|
||||
|
||||
this.setGameScores(gameScore, winningTeam, isSoloPlay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the score according to card points and announcements in case of a "normal" game, so without unfulfilled announcements
|
||||
* @param winningTeamScore
|
||||
* @param winningTeam
|
||||
* @private
|
||||
*/
|
||||
private calculateNormalScore(winningTeamScore: number, winningTeam: Team): number {
|
||||
let gameScore = 1; // 1 Point for Winning
|
||||
|
||||
// Won by how much?
|
||||
if (winningTeamScore > 210) {
|
||||
gameScore += 3;
|
||||
} else if (winningTeamScore > 180) {
|
||||
gameScore += 2;
|
||||
} else if (winningTeamScore > 150) {
|
||||
gameScore += 1;
|
||||
}
|
||||
|
||||
// Announcements
|
||||
if (winningTeam === Team.RE) {
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE_NO_NINETY) && winningTeamScore > 150) {
|
||||
gameScore++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE_NO_SIXTY) && winningTeamScore > 180) {
|
||||
gameScore++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE_NO_THIRTY) && winningTeamScore > 210) {
|
||||
gameScore++;
|
||||
}
|
||||
}
|
||||
if (winningTeam === Team.CONTRA) {
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA_NO_NINETY) && winningTeamScore > 150) {
|
||||
gameScore++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA_NO_SIXTY) && winningTeamScore > 180) {
|
||||
gameScore++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA_NO_THIRTY) && winningTeamScore > 210) {
|
||||
gameScore++;
|
||||
}
|
||||
}
|
||||
|
||||
return gameScore;
|
||||
}
|
||||
@@ -282,4 +487,237 @@ export class AddGameComponent implements OnInit {
|
||||
|
||||
return totalTeamScore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates which team won and returns the Team Name and the achieved score
|
||||
*/
|
||||
getWinningTeamAndScore(): { team: Team, score: number } {
|
||||
let elderPoints: number = 0;
|
||||
let otherPoints: number = 0;
|
||||
|
||||
for (let player of this.actualPlayers) {
|
||||
if (player.team === Team.RE) {
|
||||
elderPoints += player.finalCardScore ?? 0;
|
||||
} else {
|
||||
otherPoints += player.finalCardScore ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (elderPoints > otherPoints) {
|
||||
return {
|
||||
team: Team.RE,
|
||||
score: elderPoints
|
||||
};
|
||||
}
|
||||
return {
|
||||
team: Team.CONTRA,
|
||||
score: otherPoints
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the game scores for all players
|
||||
* @param score The score to set
|
||||
* @param winningTeam The team that won
|
||||
*/
|
||||
setGameScores(score: number, winningTeam: Team, isSolo: boolean) {
|
||||
for (let player of this.actualPlayers) {
|
||||
if (player.team === winningTeam) {
|
||||
if(isSolo) {
|
||||
player.gamePoints = score * 3;
|
||||
} else {
|
||||
player.gamePoints = score;
|
||||
}
|
||||
} else {
|
||||
player.gamePoints = -score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the points that each team got by catching foxes
|
||||
*/
|
||||
calculateFoxPoints(): { re: number, contra: number } {
|
||||
let reFoxesCaught: number = 0;
|
||||
let contraFoxesCaught: number = 0;
|
||||
|
||||
for (let player of this.actualPlayers) {
|
||||
if (player.team === Team.RE) {
|
||||
reFoxesCaught += player.foxesCaught ?? 0;
|
||||
} else {
|
||||
contraFoxesCaught += player.foxesCaught ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
re: reFoxesCaught,
|
||||
contra: contraFoxesCaught
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the final fox points for the winning team
|
||||
* @param winningTeam The winning team
|
||||
*/
|
||||
getFinalFoxPoints(winningTeam: Team): number {
|
||||
let finalPoints = 0;
|
||||
|
||||
if (winningTeam === Team.RE) {
|
||||
finalPoints += this.calculateFoxPoints().re;
|
||||
finalPoints -= this.calculateFoxPoints().contra;
|
||||
} else {
|
||||
finalPoints += this.calculateFoxPoints().contra;
|
||||
finalPoints -= this.calculateFoxPoints().re;
|
||||
}
|
||||
|
||||
return finalPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extra points for a when a charlie made the final trick.
|
||||
* If the winning team played the charlie, they get one point. If the losing team played the charlie, the winning team loses one point.
|
||||
* @param winningTeam The winning team
|
||||
*/
|
||||
getCharliePoints(winningTeam: Team): number {
|
||||
for (let player of this.actualPlayers) {
|
||||
if (player.wonLastTrickWithCharlie) {
|
||||
return player.team === winningTeam ? 1 : -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the winning team has made announcements that have not been fulfilled.
|
||||
* If so, returns the points that the "losing" team gets for these unfulfilled announcements
|
||||
* @param normalWinningTeam The team that would have won under normal circumstances
|
||||
* @param normalWinningTeamScore The card score of said team
|
||||
*/
|
||||
checkUnfulfilledAnnouncements(normalWinningTeam: Team, normalWinningTeamScore: number): number {
|
||||
let gamePoints = 0;
|
||||
|
||||
if (normalWinningTeam === Team.RE) {
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE_NO_NINETY) && normalWinningTeamScore < 151) {
|
||||
gamePoints++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE_NO_SIXTY) && normalWinningTeamScore < 181) {
|
||||
gamePoints++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.RE_NO_THIRTY) && normalWinningTeamScore < 211) {
|
||||
gamePoints++;
|
||||
}
|
||||
}
|
||||
if (normalWinningTeam === Team.CONTRA) {
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA_NO_NINETY) && normalWinningTeamScore < 151) {
|
||||
gamePoints++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA_NO_SIXTY) && normalWinningTeamScore < 181) {
|
||||
gamePoints++;
|
||||
}
|
||||
if (this.checkAnnouncementActive(announcements.Announcement.CONTRA_NO_THIRTY) && normalWinningTeamScore < 211) {
|
||||
gamePoints++;
|
||||
}
|
||||
}
|
||||
|
||||
return gamePoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* _____ __
|
||||
* / ___/____ / /___
|
||||
* \__ \/ __ \/ / __ \
|
||||
* ___/ / /_/ / / /_/ /
|
||||
* /____/\____/_/\____/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks, according to the assigned Teams, if this is a solo play
|
||||
*/
|
||||
checkIfSolo(): boolean {
|
||||
let numberOfElders: number = 0;
|
||||
|
||||
for(let player of this.actualPlayers) {
|
||||
if(player.team === Team.RE) {
|
||||
numberOfElders++;
|
||||
}
|
||||
}
|
||||
|
||||
return numberOfElders === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given solo is currently active
|
||||
* @param solo The solo to check active status for
|
||||
*/
|
||||
isSoloActive(solo: solos.Solo): boolean {
|
||||
return this.soloPlayed === solo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all possible solo values
|
||||
*/
|
||||
getAllPossibleSolos(): solos.Solo[] {
|
||||
return solos.getAllSoloValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the given solo as the active one
|
||||
* @param solo The solo to set as the active one
|
||||
*/
|
||||
toggleSolo(solo: solos.Solo): void {
|
||||
this.soloPlayed = solo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is a solo selected, false otherwise
|
||||
*/
|
||||
noSoloSelectedYet(): boolean {
|
||||
return this.soloPlayed === undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* ______ __ ____ _ __
|
||||
* / ____/ __/ /__________ _ / __ \____ (_)___ / /______
|
||||
* / __/ | |/_/ __/ ___/ __ `/ / /_/ / __ \/ / __ \/ __/ ___/
|
||||
* / /____> </ /_/ / / /_/ / / ____/ /_/ / / / / / /_(__ )
|
||||
* /_____/_/|_|\__/_/ \__,_/ /_/ \____/_/_/ /_/\__/____/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks if the number of caught foxes checks out
|
||||
*/
|
||||
checkTotalFoxPoints(): boolean {
|
||||
let totalFoxPoints: number = 0;
|
||||
|
||||
for (let player of this.actualPlayers) {
|
||||
totalFoxPoints += player.foxesCaught ?? 0;
|
||||
}
|
||||
|
||||
return totalFoxPoints <= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all extra point types have valid entries
|
||||
*/
|
||||
checkAllExtraPoints(): boolean {
|
||||
return this.checkTotalFoxPoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* _____
|
||||
* / ___/__ ______ ___ ____ ___ ____ ________ __
|
||||
* \__ \/ / / / __ `__ \/ __ `__ \/ __ `/ ___/ / / /
|
||||
* ___/ / /_/ / / / / / / / / / / / /_/ / / / /_/ /
|
||||
* /____/\__,_/_/ /_/ /_/_/ /_/ /_/\__,_/_/ \__, /
|
||||
* /____/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sends the game stats to the API to be saved
|
||||
*/
|
||||
saveGame(): void {
|
||||
//TODO implement
|
||||
// call api method, then return to gameNight page / close modal or sth like that
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ export enum Announcement {
|
||||
export function getAllAnnouncementValues(): Announcement[] {
|
||||
return [
|
||||
Announcement.RE,
|
||||
Announcement.CONTRA,
|
||||
Announcement.RE_NO_NINETY,
|
||||
Announcement.CONTRA_NO_NINETY,
|
||||
Announcement.RE_NO_SIXTY,
|
||||
Announcement.CONTRA_NO_SIXTY,
|
||||
Announcement.RE_NO_THIRTY,
|
||||
Announcement.CONTRA,
|
||||
Announcement.CONTRA_NO_NINETY,
|
||||
Announcement.CONTRA_NO_SIXTY,
|
||||
Announcement.CONTRA_NO_THIRTY
|
||||
];
|
||||
}
|
||||
@@ -28,8 +28,7 @@ export function getAllAnnouncementValues(): Announcement[] {
|
||||
/**
|
||||
* Checks if the selected announcements are a valid set of announcements.
|
||||
* E.g.: If RE_NO_NINETY is newly selected, RE also has to be selected
|
||||
* @param alreadySelected
|
||||
* @param newSelected
|
||||
* @param selectedAnnouncements The list of selected announcements
|
||||
*/
|
||||
export function checkValidity(selectedAnnouncements: Announcement[]): boolean {
|
||||
// First check all "RE" Announcements
|
||||
@@ -70,6 +69,10 @@ export function checkValidity(selectedAnnouncements: Announcement[]): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the two highest announcements from the given list, one for RE and one for CONTRA if applicable
|
||||
* @param selectedAnnouncements The list of announcements to check
|
||||
*/
|
||||
export function returnTwoHighestAnnouncements(selectedAnnouncements: Announcement[]): string {
|
||||
let finalString: string = '';
|
||||
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
export enum Solo {
|
||||
QUEENS = 0,
|
||||
JACKS = 1,
|
||||
COLOR_CHECKS = 2,
|
||||
COLOR_HEART = 3,
|
||||
COLOR_SPADES = 4,
|
||||
COLOR_CROSS = 5,
|
||||
FLESHLESS = 6
|
||||
QUEENS = 'Queens',
|
||||
JACKS = 'Jacks',
|
||||
COLOR_CHECKS = 'Checks',
|
||||
COLOR_HEART = 'Heart',
|
||||
COLOR_SPADES = 'Spades',
|
||||
COLOR_CROSS = 'Cross',
|
||||
FLESHLESS = 'Fleshless'
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all available solo values
|
||||
*/
|
||||
export function getAllSoloValues(): Solo[] {
|
||||
return [
|
||||
Solo.QUEENS,
|
||||
Solo.JACKS,
|
||||
Solo.COLOR_CHECKS,
|
||||
Solo.COLOR_HEART,
|
||||
Solo.COLOR_SPADES,
|
||||
Solo.COLOR_CROSS,
|
||||
Solo.FLESHLESS
|
||||
];
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import {Solo} from './enums/solo';
|
||||
export interface Game {
|
||||
gameId: number;
|
||||
players: Player[];
|
||||
foxesCaught: number;
|
||||
announcements: Announcement[];
|
||||
solo?: Solo;
|
||||
againstTheElders: boolean;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ export interface Player {
|
||||
firebonkId: number;
|
||||
uuid: string;
|
||||
firstName: string;
|
||||
finalCardScore?: number;
|
||||
gamePoints?: number;
|
||||
finalCardScore: number;
|
||||
gamePoints: number;
|
||||
hadMarriage?: boolean;
|
||||
hadTrumpHandoff?: boolean;
|
||||
team?: Team;
|
||||
foxesCaught?: number;
|
||||
wonLastTrickWithCharlie?: boolean;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,20 @@ export class HomeComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// TODO: First try to read existing session data
|
||||
if(!HomeComponent.sessionDataAvailable()) {
|
||||
this.authenticateUser();
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is session data saved in the local storage
|
||||
* @return If there is session data available
|
||||
*/
|
||||
private static sessionDataAvailable(): boolean {
|
||||
let user = StorageService.getUserInfo();
|
||||
|
||||
return user !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,6 +47,10 @@ export class HomeComponent implements OnInit {
|
||||
sessionKey: ''
|
||||
};
|
||||
|
||||
if(user.firebonkId === undefined || user.firstName === undefined || user.token === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let authenticatedUser = ApiService.performAuthentication(user);
|
||||
StorageService.setUserInfo(authenticatedUser);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user