diff --git a/package-lock.json b/package-lock.json
index e858c06..47a88fb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,7 +24,7 @@
"i": "^0.3.7",
"jquery": "^3.6.0",
"npm": "^10.2.3",
- "rxjs": "~6.6.0",
+ "rxjs": "^7.8.1",
"socket.io-client": "^4.2.0",
"tslib": "^2.3.0",
"zone.js": "~0.13.3"
@@ -71,15 +71,6 @@
"yarn": ">= 1.13.0"
}
},
- "node_modules/@angular-devkit/architect/node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/@angular-devkit/build-angular": {
"version": "16.2.9",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.9.tgz",
@@ -241,15 +232,6 @@
"vite": "^3.0.0 || ^4.0.0"
}
},
- "node_modules/@angular-devkit/build-angular/node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/@angular-devkit/build-angular/node_modules/vite": {
"version": "4.4.7",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz",
@@ -324,15 +306,6 @@
"webpack-dev-server": "^4.0.0"
}
},
- "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/@angular-devkit/core": {
"version": "16.2.9",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.9.tgz",
@@ -360,15 +333,6 @@
}
}
},
- "node_modules/@angular-devkit/core/node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/@angular-devkit/schematics": {
"version": "16.2.9",
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.9.tgz",
@@ -387,15 +351,6 @@
"yarn": ">= 1.13.0"
}
},
- "node_modules/@angular-devkit/schematics/node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/@angular/animations": {
"version": "16.2.12",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.12.tgz",
@@ -7331,15 +7286,6 @@
"node": ">=8"
}
},
- "node_modules/inquirer/node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/inquirer/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -13424,21 +13370,14 @@
}
},
"node_modules/rxjs": {
- "version": "6.6.7",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
- "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^1.9.0"
- },
- "engines": {
- "npm": ">=2.0.0"
+ "tslib": "^2.1.0"
}
},
- "node_modules/rxjs/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -15627,17 +15566,6 @@
"requires": {
"@angular-devkit/core": "16.2.9",
"rxjs": "7.8.1"
- },
- "dependencies": {
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- }
}
},
"@angular-devkit/build-angular": {
@@ -15738,15 +15666,6 @@
"dev": true,
"requires": {}
},
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- },
"vite": {
"version": "4.4.7",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz",
@@ -15769,17 +15688,6 @@
"requires": {
"@angular-devkit/architect": "0.1602.9",
"rxjs": "7.8.1"
- },
- "dependencies": {
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- }
}
},
"@angular-devkit/core": {
@@ -15794,17 +15702,6 @@
"picomatch": "2.3.1",
"rxjs": "7.8.1",
"source-map": "0.7.4"
- },
- "dependencies": {
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- }
}
},
"@angular-devkit/schematics": {
@@ -15818,17 +15715,6 @@
"magic-string": "0.30.1",
"ora": "5.4.1",
"rxjs": "7.8.1"
- },
- "dependencies": {
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- }
}
},
"@angular/animations": {
@@ -20871,15 +20757,6 @@
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- },
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -25090,18 +24967,11 @@
}
},
"rxjs": {
- "version": "6.6.7",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
- "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"requires": {
- "tslib": "^1.9.0"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
+ "tslib": "^2.1.0"
}
},
"safe-buffer": {
diff --git a/package.json b/package.json
index afafcf0..808906e 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"i": "^0.3.7",
"jquery": "^3.6.0",
"npm": "^10.2.3",
- "rxjs": "~6.6.0",
+ "rxjs": "^7.8.1",
"socket.io-client": "^4.2.0",
"tslib": "^2.3.0",
"zone.js": "~0.13.3"
diff --git a/src/app/admin/admin-testing/admin-testing.component.html b/src/app/admin/admin-testing/admin-testing.component.html
index 98182b6..9b9c020 100644
--- a/src/app/admin/admin-testing/admin-testing.component.html
+++ b/src/app/admin/admin-testing/admin-testing.component.html
@@ -4,11 +4,12 @@
Game
+
Versus
-
+
diff --git a/src/app/admin/admin-testing/admin-testing.component.ts b/src/app/admin/admin-testing/admin-testing.component.ts
index aac42ab..d3f56fa 100644
--- a/src/app/admin/admin-testing/admin-testing.component.ts
+++ b/src/app/admin/admin-testing/admin-testing.component.ts
@@ -49,4 +49,8 @@ export class AdminTestingComponent implements OnInit, OnDestroy {
clearGameQueue() {
this.testingApiService.clearGameQueue().pipe(takeUntil(this.destroyed$)).subscribe((r => console.log(r)));
}
+
+ simulateEndGamePoints() {
+ this.testingApiService.simulateEndGamePoints().pipe(takeUntil(this.destroyed$)).subscribe(r => console.log(r));
+ }
}
diff --git a/src/app/admin/components/main-actions/main-actions.component.ts b/src/app/admin/components/main-actions/main-actions.component.ts
index f5c5c3c..6925519 100644
--- a/src/app/admin/components/main-actions/main-actions.component.ts
+++ b/src/app/admin/components/main-actions/main-actions.component.ts
@@ -25,6 +25,7 @@ export class MainActionsComponent implements OnInit {
{ title: 'Registration', name: 'register'},
{ title: 'Onboarding', name: 'onboarding' },
{ title: 'Start quiz', name: 'quiz' },
+ { title: 'Endgame Points', name: 'endgamepoints' },
{ title: 'End', name: 'finish' },
];
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 02f5a9f..e6ac10a 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -6,6 +6,7 @@ import { RegisterComponent } from "./views/register/register.component";
import { OnboardingComponent } from "./views/onboarding/onboarding.component";
import { InitialComponent } from './views/initial/initial.component';
import { FinishComponent } from './views/finish/finish.component';
+import {EndgamepointsComponent} from "./views/endgamepoints/endgamepoints.component";
const routes: Routes = [
{ path: 'quiz', component: QuizComponent },
@@ -14,6 +15,7 @@ const routes: Routes = [
{ path: 'onboarding', component: OnboardingComponent },
{ path: 'initial', component: InitialComponent },
{ path: 'finish', component: FinishComponent },
+ { path: 'endgamepoints', component: EndgamepointsComponent },
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)},
];
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f6ef8ff..abee8ec 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -28,6 +28,7 @@ import { FinishComponent } from './views/finish/finish.component';
import { InitialComponent } from './views/initial/initial.component';
import { SkrepaComponent } from './components/skrepa/skrepa.component';
import { VersusComponent } from './components/versus/versus.component';
+import { EndgamepointsComponent } from './views/endgamepoints/endgamepoints.component';
@NgModule({
declarations: [
@@ -52,6 +53,7 @@ import { VersusComponent } from './components/versus/versus.component';
InitialComponent,
SkrepaComponent,
VersusComponent,
+ EndgamepointsComponent,
],
imports: [
BrowserModule,
diff --git a/src/app/components/game-queue/game-queue.component.html b/src/app/components/game-queue/game-queue.component.html
index cd5d043..3413d44 100644
--- a/src/app/components/game-queue/game-queue.component.html
+++ b/src/app/components/game-queue/game-queue.component.html
@@ -31,18 +31,24 @@
-
0 || results.invalid.length > 0)">
-
Результаты
-
Ответили правильно
-
-
+
+
0">Ответили правильно
-
Не смогли
-
diff --git a/src/app/components/participant-item/participant-item.component.html b/src/app/components/participant-item/participant-item.component.html
index eb252cd..76ca1ac 100644
--- a/src/app/components/participant-item/participant-item.component.html
+++ b/src/app/components/participant-item/participant-item.component.html
@@ -1,9 +1,9 @@
-
+
- {{ participant?.name }}
+ {{ participant.name }}
diff --git a/src/app/components/question/question.component.ts b/src/app/components/question/question.component.ts
index 398121e..a6e885c 100644
--- a/src/app/components/question/question.component.ts
+++ b/src/app/components/question/question.component.ts
@@ -17,7 +17,7 @@ export class QuestionComponent implements OnInit, OnDestroy {
private questionSubscription: Subscription;
countdownInterval:ReturnType|null= null;
countdown = 0;
- readonly countDownTimer =20;
+ readonly countDownTimer = 20;
constructor(private apiService:ApiService, private eventService: EventService, private voiceService: VoiceService) { }
diff --git a/src/app/components/versus/versus.component.html b/src/app/components/versus/versus.component.html
index 65e881b..9755b3d 100644
--- a/src/app/components/versus/versus.component.html
+++ b/src/app/components/versus/versus.component.html
@@ -21,4 +21,5 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/src/app/services/api.service.ts b/src/app/services/api.service.ts
index b712ff3..4875104 100644
--- a/src/app/services/api.service.ts
+++ b/src/app/services/api.service.ts
@@ -13,7 +13,7 @@ import {QuestionresultsDto} from "../../types/questionresults.dto";
import {map} from "rxjs/operators";
import {VersusItem} from "../../types/versus-item";
-export interface FeatureFlagStateDto {
+export class FeatureFlagStateDto {
name: string;
state: boolean;
}
@@ -34,6 +34,24 @@ export interface ConfigRecordDto {
value: string;
}
+export interface EndgameResultsDto {
+ maxInvalidAnswers: {
+ id: number;
+ count: number;
+ name: string;
+ },
+ maxRewards: {
+ id: number;
+ count: number;
+ name: string;
+ },
+ maxPenalties: {
+ id: number;
+ count: number;
+ name: string;
+ }
+}
+
@Injectable({
providedIn: 'root'
})
@@ -115,7 +133,14 @@ export class ApiService {
}
getQuestionResults() {
- return this.httpClient.get
(`${API_URL}/quiz/question-results`)
+ return this.httpClient.get(`${API_URL}/quiz/question-results`).pipe(map((data) =>
+ data.map((item) => {
+ return {
+ ...item,
+ time: new Date(item.time)
+ }
+ })
+ ));
}
getFeatureFlagState(feature: string) {
@@ -140,4 +165,8 @@ export class ApiService {
loser: loser
});
}
+
+ getEndgameResults() {
+ return this.httpClient.get(`${API_URL}/quiz/endgame-results`)
+ }
}
diff --git a/src/app/services/testing-api.service.ts b/src/app/services/testing-api.service.ts
index 76a15e5..c723891 100644
--- a/src/app/services/testing-api.service.ts
+++ b/src/app/services/testing-api.service.ts
@@ -24,4 +24,8 @@ export class TestingApiService {
clearGameQueue() {
return this.httpClient.post(`${API_URL}/game/clear-queue`, {});
}
+
+ simulateEndGamePoints() {
+ return this.httpClient.post(`${API_URL}/quiz/calculate-endgame-extrapoints`, {})
+ }
}
diff --git a/src/app/services/voice.service.ts b/src/app/services/voice.service.ts
index 3341ca6..956dca9 100644
--- a/src/app/services/voice.service.ts
+++ b/src/app/services/voice.service.ts
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http";
import { API_URL } from "../../app.constants";
-import { Subject } from "rxjs";
+import {Observable, of, Subject} from "rxjs";
@Injectable({
providedIn: 'root'
@@ -17,6 +17,19 @@ export class VoiceService {
this.voiceSubject.next(url);
}
+ playAudio$(url: string) {
+ this.voiceSubject.next(url);
+ return new Observable((observer) => {
+ const subscription = this.audioEndedSubject.subscribe({
+ next: () => {
+ observer.next(null);
+ observer.complete();
+ }
+ });
+ return () => subscription.unsubscribe();
+ })
+ }
+
getAudioUrl(text: string,voice: number = 1) {
return `${API_URL}/voice/tts?voice=${voice}&text=${text}`
}
diff --git a/src/app/shared/featureflags.ts b/src/app/shared/featureflags.ts
index c78fa83..96b765f 100644
--- a/src/app/shared/featureflags.ts
+++ b/src/app/shared/featureflags.ts
@@ -4,5 +4,6 @@ export class FeatureFlagList {
"DontMarkQuestionsAsCompleted",
"DisableVoice",
"ProdMode",
+ "EndgamePointsUseCssAnimation",
];
}
\ No newline at end of file
diff --git a/src/app/shared/sharedmethods.ts b/src/app/shared/sharedmethods.ts
new file mode 100644
index 0000000..37be26b
--- /dev/null
+++ b/src/app/shared/sharedmethods.ts
@@ -0,0 +1,5 @@
+export class SharedMethods {
+ static sleep(ms: number) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+ }
+}
\ No newline at end of file
diff --git a/src/app/views/endgamepoints/endgamepoints.component.html b/src/app/views/endgamepoints/endgamepoints.component.html
new file mode 100644
index 0000000..edae027
--- /dev/null
+++ b/src/app/views/endgamepoints/endgamepoints.component.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+ Время наградить особо отличившихся!
+
+
+
+ За тяжелую судьбу +2
+
+
+
+
+
+ За полный успех -2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Время наградить особо отличившихся!
+
+
+
+ За тяжелую судьбу
+2
+
+
+
+
+
+ За полный успех
−2
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/views/endgamepoints/endgamepoints.component.scss b/src/app/views/endgamepoints/endgamepoints.component.scss
new file mode 100644
index 0000000..102b8a9
--- /dev/null
+++ b/src/app/views/endgamepoints/endgamepoints.component.scss
@@ -0,0 +1,202 @@
+$shooting-time: 3000ms;
+
+@keyframes slideInUp {
+ 0% {
+ transform: translateY(3000%);
+ }
+ 100% {
+ transform: translateY(0);
+ }
+}
+
+@keyframes opacityIn {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes fontSizeTitle {
+ 0% {
+ font-size: 1em;
+ }
+ 100% {
+ font-size: 2em;
+ }
+
+}
+
+.background-video {
+ position: relative;
+ height: 100vh; /* Full viewport height */
+ width: 100%; /* Full width */
+ overflow: hidden;
+}
+
+.dark-container {
+ position:relative;
+ height: 100vh;
+ width: 100%;
+ overflow: hidden;
+ background-color: #000220;
+}
+.background-video video {
+ position: absolute;
+ width: 100%;
+ height: 100vh;
+ object-fit: cover; /* Ensures the video covers the container */
+ z-index: -1; /* Places the video behind the content */
+}
+
+.content {
+ color: white;
+ position: absolute;
+ top: 50px;
+ left: 20px;
+ right: 20px;
+ z-index: 100;
+ text-align: center;
+ font-family: Arial, sans-serif;
+ padding: 20px;
+}
+
+.text-announce {
+ margin-top: 15%;
+ font-size: 2em;
+ font-weight: bold;
+ animation: slideInUp 1s forwards, fontSizeTitle 1s forwards, opacityIn 1s forwards;
+}
+
+.shooting_star {
+ position: absolute;
+ left: 10%;
+ top: 10%;
+ // width: 100px;
+ height: 2px;
+ background: linear-gradient(-45deg, rgb(243, 227, 6), rgba(0, 0, 255, 0));
+ border-radius: 999px;
+ filter: drop-shadow(0 0 6px rgb(250, 253, 148));
+ animation:
+ tail $shooting-time ease-in-out infinite,
+ shooting $shooting-time ease-in-out infinite;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: calc(50% - 1px);
+ right: 0;
+ // width: 30px;
+ height: 2px;
+ background: linear-gradient(-45deg, rgba(0, 0, 255, 0), rgba(95, 145, 255, 1), rgba(0, 0, 255, 0));
+ transform: translateX(50%) rotateZ(45deg);
+ border-radius: 100%;
+ animation: shining $shooting-time ease-in-out infinite;
+ }
+
+ &::after {
+ // CodePen Error
+ // @extend .shooting_star::before;
+
+ content: '';
+ position: absolute;
+ top: calc(50% - 1px);
+ right: 0;
+ // width: 30px;
+ height: 2px;
+ background: linear-gradient(-45deg, rgba(0, 0, 255, 0), rgba(95, 145, 255, 1), rgba(0, 0, 255, 0));
+ transform: translateX(50%) rotateZ(45deg);
+ border-radius: 100%;
+ animation: shining $shooting-time ease-in-out infinite;
+ transform: translateX(50%) rotateZ(-45deg);
+ }
+
+ @for $i from 1 through 20 {
+ &:nth-child(#{$i}) {
+ $delay: random(9999) + 0ms;
+ top: calc(50% - #{random(2000) - 200px});
+ left: calc(50% - #{random(300) + 0px});
+ animation-delay: $delay;
+ opacity: random(50) / 100 + 0.5;
+
+ &::before,
+ &::after {
+ animation-delay: $delay;
+ }
+ }
+ }
+}
+
+@keyframes tail {
+ 0% {
+ width: 0;
+ }
+
+ 30% {
+ width: 100px;
+ }
+
+ 100% {
+ width: 0;
+ }
+}
+
+@keyframes shining {
+ 0% {
+ width: 0;
+ }
+
+ 50% {
+ width: 30px;
+ }
+
+ 100% {
+ width: 0;
+ }
+}
+
+@keyframes shooting {
+ 0% {
+ transform: translateX(0);
+ }
+
+ 100% {
+ transform: translateX(300px);
+ }
+}
+
+@keyframes sky {
+ 0% {
+ transform: rotate(45deg);
+ }
+
+ 100% {
+ transform: rotate(45 + 360deg);
+ }
+}
+
+
+@keyframes glow {
+ 0% {
+ text-shadow: 0 0 2px #f5f5f5, 0 0 10px #f5f5f5, 0 0 20px #ffc14d, 0 0 30px #fff1e0, 0 0 40px #ff4da6, 0 0 50px #ff4da6, 0 0 75px #ff4da6;
+ }
+ 100% {
+ text-shadow: 0 0 20px #ffffff, 0 0 20px #ff0080, 0 0 30px #ff0080, 0 0 40px #ff0080, 0 0 50px #ff0080, 0 0 75px #ff0080, 0 0 100px #ff0080;
+ }
+}
+.night {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ transform: rotateZ(45deg);
+ animation: sky 100000ms linear infinite;
+}
+
+.score {
+ background-color: #f8b12c;
+ border-radius: 50%;
+ padding: 10px;
+ text-shadow: 0 0 5px #f5f5f5, 0 0 10px #f5f5f5, 0 0 20px #ff4da6, 0 0 30px #ff4da6, 0 0 40px #ff4da6, 0 0 50px #ff4da6, 0 0 75px #ff4da6;
+ animation: glow 2s infinite alternate;
+}
\ No newline at end of file
diff --git a/src/app/views/endgamepoints/endgamepoints.component.spec.ts b/src/app/views/endgamepoints/endgamepoints.component.spec.ts
new file mode 100644
index 0000000..f4f8e6e
--- /dev/null
+++ b/src/app/views/endgamepoints/endgamepoints.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { EndgamepointsComponent } from './endgamepoints.component';
+
+describe('EndgamepointsComponent', () => {
+ let component: EndgamepointsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [EndgamepointsComponent]
+ });
+ fixture = TestBed.createComponent(EndgamepointsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/views/endgamepoints/endgamepoints.component.ts b/src/app/views/endgamepoints/endgamepoints.component.ts
new file mode 100644
index 0000000..7f7806f
--- /dev/null
+++ b/src/app/views/endgamepoints/endgamepoints.component.ts
@@ -0,0 +1,99 @@
+import {Component, OnInit} from '@angular/core';
+import {ApiService, EndgameResultsDto, FeatureFlagStateDto} from "../../services/api.service";
+import {
+ of,
+ Subject,
+ lastValueFrom,
+ firstValueFrom,
+ mergeWith,
+ combineLatestAll,
+ combineLatest,
+ mergeMap,
+ forkJoin, merge
+} from "rxjs";
+import { takeUntil} from "rxjs/operators";
+import {VoiceService} from "../../services/voice.service";
+import {animate, keyframes, style, transition, trigger} from "@angular/animations";
+import {Participant} from "../../../types/participant";
+import {SharedMethods} from "../../shared/sharedmethods";
+
+@Component({
+ selector: 'app-endgamepoints',
+ templateUrl: './endgamepoints.component.html',
+ styleUrls: ['./endgamepoints.component.scss'],
+ animations: [
+ trigger('slideOut', [
+ transition(':leave', [
+ animate(
+ '1300ms ease-in',
+ style({ transform: 'translateY(-100%)', opacity: 0 })
+ ),
+ ]),
+ ])]
+})
+export class EndgamepointsComponent implements OnInit{
+ loaded = false;
+ useCssAnimation = false;
+ destroyed$ = new Subject();
+ showInitialText = true;
+ showMaxAmountOfInvalidAnswers = false;
+ endgameResults: EndgameResultsDto | null;
+ participants: Participant[] = [];
+ maxAmountOfPenalties = false;
+ maxAmountOfRewards = false;
+ constructor(private apiService: ApiService, private voiceService: VoiceService) {
+ }
+
+
+ ngOnInit(): void {
+ const ff$ = this.apiService.getFeatureFlagState("EndgamePointsUseCssAnimation");
+ // @ts-ignore
+ const results$ = this.apiService.getEndgameResults();
+ combineLatest([results$, ff$])
+ .pipe(takeUntil(this.destroyed$))
+ .subscribe(([results,ff]) => {
+ const userData$ = [];
+ userData$.push(
+ this.apiService.getParticipant(results.maxInvalidAnswers.id),
+ this.apiService.getParticipant(results.maxPenalties.id),
+ this.apiService.getParticipant(results.maxRewards.id),
+ );
+ merge(...userData$).pipe(takeUntil(this.destroyed$)).subscribe((r) => this.participants.push(r));
+ this.useCssAnimation = ff.state;
+ this.endgameResults = results;
+ this.loaded = true;
+ this.playScene().then(() => {});
+ console.log(results);
+ });
+ }
+
+
+ async playScene() {
+ await firstValueFrom(this.voiceService.playAudio$(this.voiceService.getAudioUrl("Время наградить особо отличившихся!")));
+ this.showInitialText = false;
+ await SharedMethods.sleep(1000);
+ this.showMaxAmountOfInvalidAnswers = true;
+ await SharedMethods.sleep(500);
+ await firstValueFrom(this.voiceService.playAudio$(this.voiceService.getAudioUrl(` За максимальное количество неверных ответов, плюс два очка получает ${this.endgameResults?.maxInvalidAnswers.name}`)));
+ this.showMaxAmountOfInvalidAnswers = false;
+ await SharedMethods.sleep(3000);
+ this.maxAmountOfPenalties = true;
+ await firstValueFrom(this.voiceService.playAudio$(this.voiceService.getAudioUrl(`За самое большое количество полученных наказаний плюс два очка получил ${this.endgameResults?.maxPenalties.name}`)));
+ await SharedMethods.sleep(3000)
+ this.maxAmountOfPenalties = false;
+ await firstValueFrom(this.voiceService.playAudio$(this.voiceService.getAudioUrl(`И чтобы сделать игру более справедливой, есть последняя номинация`)));
+ this.maxAmountOfRewards = true;
+ await firstValueFrom(this.voiceService.playAudio$(this.voiceService.getAudioUrl(`${this.endgameResults?.maxRewards.name} лишается двух очков за свой невероятный ум`)));
+ await SharedMethods.sleep(15000);
+
+ }
+
+
+ getParticipant(id: number | undefined): Participant|null {
+ if(id) {
+ const p = this.participants.find(x => x.telegramId === id);
+ return p !== undefined ? p : null;
+ }
+ return null;
+ }
+}
diff --git a/src/app/views/onboarding/onboarding.component.ts b/src/app/views/onboarding/onboarding.component.ts
index 53d5fc8..1c397d8 100644
--- a/src/app/views/onboarding/onboarding.component.ts
+++ b/src/app/views/onboarding/onboarding.component.ts
@@ -118,7 +118,6 @@ export class OnboardingComponent implements OnInit, OnDestroy {
}
shakeCard(card: ElementRef) {
- console.log(`shake card`);
this.renderer.addClass(card.nativeElement, 'shake');
this.renderer.addClass(card.nativeElement, 'zoom-in');
if(!this.allRulesAnnounced) {
@@ -142,7 +141,6 @@ export class OnboardingComponent implements OnInit, OnDestroy {
}
stopShaking(card: ElementRef) {
- console.log(`stop shacking`);
this.renderer.removeClass(card.nativeElement, 'shake');
}
diff --git a/src/assets/endgame/1469-147538044.mp4 b/src/assets/endgame/1469-147538044.mp4
new file mode 100644
index 0000000..771f3d3
Binary files /dev/null and b/src/assets/endgame/1469-147538044.mp4 differ
diff --git a/src/assets/endgame/48569-454825064.mp4 b/src/assets/endgame/48569-454825064.mp4
new file mode 100644
index 0000000..2199982
Binary files /dev/null and b/src/assets/endgame/48569-454825064.mp4 differ
diff --git a/src/assets/endgame/energetic-bgm-242515.mp3 b/src/assets/endgame/energetic-bgm-242515.mp3
new file mode 100644
index 0000000..c7308e9
Binary files /dev/null and b/src/assets/endgame/energetic-bgm-242515.mp3 differ
diff --git a/src/assets/versus/cinematical-epic-loop-190906.mp3 b/src/assets/versus/cinematical-epic-loop-190906.mp3
new file mode 100644
index 0000000..0ae2c1b
Binary files /dev/null and b/src/assets/versus/cinematical-epic-loop-190906.mp3 differ