- Test your command line skills
+ Test your command line skills.
You have 60 seconds to enter commands from
@@ -52,16 +52,24 @@
}}
for another try!
-
-
+
+
+
+
Hold SPACE for stats.
+
+ Press ENTER to continue.
+
diff --git a/src/app/home.component.ts b/src/app/home.component.ts
index c94d04a..0e87b7a 100644
--- a/src/app/home.component.ts
+++ b/src/app/home.component.ts
@@ -1,7 +1,9 @@
import { Component, HostListener, OnInit, ViewChild } from '@angular/core';
import {
BashbrawlterminalComponent,
- Leaderboard,
+ GameFinished,
+ LeaderboardWithLocalPlacement,
+ Score,
} from './terminals/bashbrawl/bashbrawlterminal.component';
import { LanguageCommandService } from './terminals/bashbrawl/languages/language-command.service';
import {
@@ -31,6 +33,7 @@ export class Cooldown {
width: '10vw',
minWidth: '0',
height: '10vh',
+ opacity: 0,
}),
),
state(
@@ -65,6 +68,13 @@ export class Cooldown {
maxHeight: '0vh',
}),
),
+ state(
+ 'hidden',
+ style({
+ opacity: 0,
+ maxHeight: '0vh',
+ }),
+ ),
transition('normal <=> shrunk', animate('1000ms ease-in-out')),
]),
],
@@ -72,6 +82,7 @@ export class Cooldown {
export class HomeComponent implements OnInit {
terminalState = 'hidden';
shrinkState = 'normal';
+ leaderboardState = 'normal';
badgeScanningMode = false;
gameStarted = false;
@@ -82,9 +93,16 @@ export class HomeComponent implements OnInit {
cooldown = false;
cooldownTime = '';
+ winningScreen: boolean;
+ leaderboardWithLocalPlacement: LeaderboardWithLocalPlacement;
+ score: Score;
+
@ViewChild('terminal', { static: false })
private terms: BashbrawlterminalComponent;
+ @ViewChild('instructions')
+ private instructions: HTMLElement;
+
constructor(
private languageCommandService: LanguageCommandService,
private scoreService: ScoreService,
@@ -113,6 +131,7 @@ export class HomeComponent implements OnInit {
setLargeTerminal() {
this.shrinkState = 'shrunk';
+ this.leaderboardState = 'hidden';
this.terminalState = 'large';
this.terms.resize();
}
@@ -120,16 +139,19 @@ export class HomeComponent implements OnInit {
setSmallTerminal() {
this.shrinkState = 'normal';
this.terminalState = 'small';
+ this.leaderboardState = 'hidden';
}
setHiddenTerminal() {
this.shrinkState = 'normal';
this.terminalState = 'hidden';
+ this.leaderboardState = 'normal';
}
resetToDefault() {
this.code = '';
this.gameStarted = false;
+ this.winningScreen = false;
if (this.terms) {
this.terms.clearTerminal();
@@ -137,6 +159,23 @@ export class HomeComponent implements OnInit {
this.setHiddenTerminal();
}
+ gameEnded(gameFinished: GameFinished) {
+ this.unfocusTerminal();
+
+ if (gameFinished && gameFinished.success) {
+ this.gameStarted = false;
+ this.winningScreen = true;
+ this.leaderboardState = 'normal';
+ this.shrinkState = 'shrunk';
+ this.terminalState = 'hidden';
+ this.leaderboardWithLocalPlacement =
+ gameFinished.leaderboardWithLocalPlacement;
+ this.score = gameFinished.score;
+ } else {
+ this.resetToDefault();
+ }
+ }
+
onScan(code: string) {
this.code = code;
this.cooldown = false;
@@ -179,15 +218,28 @@ export class HomeComponent implements OnInit {
}
focusTerminal() {
- setTimeout(() => this.terms.focusTerminal(), 0);
+ if (this.terminalState != 'hidden') {
+ setTimeout(() => this.terms?.focusTerminal(), 0);
+ }
+ }
+
+ unfocusTerminal() {
+ this.terms?.blurTerminal();
}
@HostListener('window:keypress', ['$event'])
protected keyEvent(event: KeyboardEvent): void {
+ console.log(event.key);
window.clearTimeout(this.scannerTimeoutId);
if (event.code === 'Space') {
this.advancedLeaderboard = true;
+ return;
+ }
+
+ if (event.key === 'Enter' && this.winningScreen) {
+ this.resetToDefault();
+ return;
}
if (event.key === 'Enter' && !this.badgeScanningMode) {
diff --git a/src/app/leaderboard/embedded/leaderboard-embedded.component.html b/src/app/leaderboard/embedded/leaderboard-embedded.component.html
index 3c85b22..a4c7bd1 100644
--- a/src/app/leaderboard/embedded/leaderboard-embedded.component.html
+++ b/src/app/leaderboard/embedded/leaderboard-embedded.component.html
@@ -13,7 +13,11 @@
-
+
| = 3">{{ i + 1 }}. |
🥇 |
🥈 |
@@ -45,5 +49,52 @@
+
+
+
+ | ... |
+ ... |
+ ... |
+
+ ... |
+ ... |
+ ... |
+ ... |
+
+
+
+
+
+ |
+ {{
+ leaderboardWithLocalPlacement.placement +
+ i -
+ getLocalScoreIndex() +
+ 1
+ }}.
+ |
+
+ {{ score.name }}
+ |
+
+ {{ score.score }}
+ |
+
+
+ {{ score.x.count }}
+ |
+
+ {{ score.x.maxStreak }}
+ |
+
+
+ {{ score.x.avgLength | number:'1.2-2' }}
+ |
+
+ {{ score.x.speed | number:'1.2-2' }}/s |
+
+
+
+
diff --git a/src/app/leaderboard/embedded/leaderboard-embedded.component.scss b/src/app/leaderboard/embedded/leaderboard-embedded.component.scss
index f601c35..f94223a 100644
--- a/src/app/leaderboard/embedded/leaderboard-embedded.component.scss
+++ b/src/app/leaderboard/embedded/leaderboard-embedded.component.scss
@@ -5,6 +5,7 @@
.leaderboard {
color: white;
font-family: monospace;
+ padding-top: 20px;
.score {
text-align: right;
@@ -27,7 +28,11 @@
}
.entry-row {
- font-size: 24px;
+ font-size: 2.5vh;
+ line-height: 2vh;
+ &.divider {
+ line-height: 1.5vh;
+ }
td {
padding: 10px;
a {
@@ -35,5 +40,10 @@
font-weight: bold;
}
}
+ &.self {
+ background-color: #74e2cd;
+ font-weight: bold;
+ color: #01162a;
+ }
}
}
diff --git a/src/app/leaderboard/embedded/leaderboard-embedded.component.ts b/src/app/leaderboard/embedded/leaderboard-embedded.component.ts
index 6b1f9ea..8df8a56 100644
--- a/src/app/leaderboard/embedded/leaderboard-embedded.component.ts
+++ b/src/app/leaderboard/embedded/leaderboard-embedded.component.ts
@@ -1,6 +1,10 @@
-import { AfterViewInit, Component, Input } from '@angular/core';
+import { AfterViewInit, Component, Input, OnChanges } from '@angular/core';
import { ScoreService } from '../../services/score.service';
-import { Leaderboard } from '../../terminals/bashbrawl/bashbrawlterminal.component';
+import {
+ Leaderboard,
+ LeaderboardWithLocalPlacement,
+ Score,
+} from '../../terminals/bashbrawl/bashbrawlterminal.component';
export class Cooldown {
cooldown: string;
@@ -11,8 +15,9 @@ export class Cooldown {
templateUrl: 'leaderboard-embedded.component.html',
styleUrls: ['leaderboard-embedded.component.scss'],
})
-export class EmbeddedLeaderboardComponent implements AfterViewInit {
+export class EmbeddedLeaderboardComponent implements AfterViewInit, OnChanges {
public leaderboard: Leaderboard;
+ public leaderboardWithLocalPlacement: LeaderboardWithLocalPlacement;
@Input()
onlyTop = 10;
@@ -23,6 +28,15 @@ export class EmbeddedLeaderboardComponent implements AfterViewInit {
@Input()
advanced = false;
+ @Input()
+ showLocalScores: boolean;
+
+ @Input()
+ score: Score;
+
+ @Input()
+ leaderboardWithLocalPlacementInput: LeaderboardWithLocalPlacement;
+
constructor(private scoreService: ScoreService) {}
ngAfterViewInit(): void {
@@ -36,8 +50,73 @@ export class EmbeddedLeaderboardComponent implements AfterViewInit {
});
}
+ ngOnChanges() {
+ if (this.leaderboardWithLocalPlacementInput && this.score) {
+ this.leaderboardWithLocalPlacement = structuredClone(
+ this.leaderboardWithLocalPlacementInput,
+ );
+ if (this.leaderboardWithLocalPlacement.placement < 10) {
+ this.onlyTop = this.showLocalScores ? 10 : 5;
+ this.leaderboardWithLocalPlacement.scores.push(this.score);
+ this.leaderboardWithLocalPlacement.scores =
+ this.leaderboardWithLocalPlacement.scores.sort(
+ (a, b) => b.score - a.score,
+ );
+ } else {
+ this.leaderboardWithLocalPlacement.localscores.push(this.score);
+ this.leaderboardWithLocalPlacement.localscores =
+ this.leaderboardWithLocalPlacement.localscores.sort(
+ (a, b) => b.score - a.score,
+ );
+ }
+
+ this.leaderboard = {
+ scores: this.leaderboardWithLocalPlacement.scores,
+ language: this.leaderboardWithLocalPlacement.language,
+ } as Leaderboard;
+ }
+ }
+
getScores() {
- return this.leaderboard?.scores ?? [];
+ return this.leaderboard?.scores.slice(0, 10) ?? [];
+ }
+
+ hasLocalScores() {
+ if (!this.showLocalScores) {
+ return false;
+ }
+ return this.leaderboardWithLocalPlacement?.localscores.length > 0;
+ }
+
+ getLocalScores() {
+ return this.hasLocalScores()
+ ? this.leaderboardWithLocalPlacement.localscores
+ : [];
+ }
+
+ getScoreIndex() {
+ if (
+ !this.leaderboardWithLocalPlacement ||
+ this.leaderboardWithLocalPlacement.placement >= 10
+ ) {
+ return -1;
+ }
+
+ return this.leaderboardWithLocalPlacement.placement;
+ }
+
+ getLocalScoreIndex() {
+ if (this.leaderboardWithLocalPlacement.placement < 10) {
+ return -1;
+ }
+
+ const scoreIndex = this.leaderboardWithLocalPlacement.localscores.findIndex(
+ (localScore) =>
+ this.score.name === localScore.name &&
+ this.score.score === localScore.score,
+ );
+
+ return scoreIndex;
}
getCodeBase64(code: string) {
diff --git a/src/app/terminals/bashbrawl/bashbrawlterminal.component.ts b/src/app/terminals/bashbrawl/bashbrawlterminal.component.ts
index 4a2bf6e..b9d7a00 100644
--- a/src/app/terminals/bashbrawl/bashbrawlterminal.component.ts
+++ b/src/app/terminals/bashbrawl/bashbrawlterminal.component.ts
@@ -20,6 +20,7 @@ import { sleep } from '@cds/core/internal';
import { LanguageCommandService } from './languages/language-command.service';
import { ScoreService } from '../../services/score.service';
import { firstValueFrom } from 'rxjs';
+import { scissorsIconName } from '@cds/core/icon';
export class Score {
name: string;
@@ -45,6 +46,12 @@ export class LeaderboardWithLocalPlacement {
localscores: Score[];
}
+export class GameFinished {
+ success: boolean;
+ leaderboardWithLocalPlacement: LeaderboardWithLocalPlacement;
+ score: Score;
+}
+
// eslint-disable-next-line no-control-regex
const stripAnsi = (str: string) => str.replace(/\x1b\[[0-9;]*m/g, '');
@@ -59,7 +66,7 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
code = '';
@Output()
- gameEnded = new EventEmitter();
+ gameEnded = new EventEmitter
();
@Output()
gameStarted = new EventEmitter();
@@ -309,7 +316,7 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
if (this.interrupted) {
this.term.write('\r\n');
- this.gameEnded.emit();
+ this.gameEnded.emit({ success: false } as GameFinished);
return;
}
@@ -317,7 +324,7 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
this.input_blocked = false;
if (this.interrupted) {
- this.gameEnded.emit();
+ this.gameEnded.emit({ success: false } as GameFinished);
return;
}
@@ -424,14 +431,6 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
this.scoreService.setScoreForLanguage(this.gameLanguage, score),
);
- await this.writeDelayed('You scored ' + score.score + '!');
- await this.writeDelayed(
- 'Your entered ' + score.x.count + ' unique commands.',
- );
- await this.writeDelayed(
- 'Your highest Streak was ' + score.x.maxStreak + '.',
- );
-
if (
leaderboardWithLocalPlacement.placement < 10 &&
leaderboardWithLocalPlacement.placement > 0
@@ -442,10 +441,17 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
}
// Add ANSI Escape Codes to format the name for the leaderboard so the current run shows in bold letters
- score.name = '>>\x1b[1;31m ' + score.name + ' \x1b[0m<<'; // \x1b[1;31m makes the text bold (1) and red (31), \x1b[0m clears all effects
+ //score.name = '>>\x1b[1;31m ' + score.name + ' \x1b[0m<<'; // \x1b[1;31m makes the text bold (1) and red (31), \x1b[0m clears all effects
- await this.writeDelayed(`Thank you for playing, ${fullName}!`);
- await this.writeDelayed(`Let's view the Leaderboard.`);
+ this.resetToDefaultShell();
+ this.input_blocked = true;
+ this.gameEnded.emit({
+ success: true,
+ leaderboardWithLocalPlacement: leaderboardWithLocalPlacement,
+ score: score,
+ } as GameFinished);
+
+ return;
await this.displayLeaderboard(
this.gameLanguage,
@@ -523,8 +529,7 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
scores.push(['...', '...', '...']);
const scoreIndex = leaderboardWithLocalPlacement.localscores.findIndex(
(localScore) =>
- score.name === localScore.name &&
- localScore.score === localScore.score,
+ score.name === localScore.name && score.score === localScore.score,
);
scores = scores.concat(
@@ -987,4 +992,8 @@ export class BashbrawlterminalComponent implements OnInit, AfterViewInit {
public focusTerminal() {
this.term.focus();
}
+
+ public blurTerminal() {
+ this.term.blur();
+ }
}
diff --git a/src/app/terminals/bashbrawl/languages/php.ts b/src/app/terminals/bashbrawl/languages/php.ts
index f8ac846..d5d5b11 100644
--- a/src/app/terminals/bashbrawl/languages/php.ts
+++ b/src/app/terminals/bashbrawl/languages/php.ts
@@ -3,7 +3,7 @@
*/
import { LanguageConfig } from './language-config.interface';
export const phpConfig: LanguageConfig = {
- name: 'php',
+ name: 'PHP 8',
cmds: [
// keywords
['and'],