docker support & updated texts

This commit is contained in:
Kirill Ivlev 2024-11-27 21:20:02 +04:00
parent 70cd2a8587
commit 5dd911fb01
18 changed files with 118 additions and 88 deletions

32
Dockerfile Normal file
View file

@ -0,0 +1,32 @@
# Stage 1: Build the Angular application
FROM node:20 as build
# Set the working directory
WORKDIR /app
# Copy package.json and package-lock.json to install dependencies
COPY package*.json ./
# Install Node.js dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the Angular application in production mode
RUN npm run build --configuration=prod
# Stage 2: Serve the app with Nginx
FROM nginx:1.21-alpine
# Copy the built app from the previous stage
COPY --from=build /app/dist/thanksgiving /usr/share/nginx/html
# Copy the custom Nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Start Nginx server
CMD ["nginx", "-g", "daemon off;"]

11
nginx.conf Normal file
View file

@ -0,0 +1,11 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}

5
package-lock.json generated
View file

@ -34,7 +34,7 @@
"@angular/cli": "^16.2.9", "@angular/cli": "^16.2.9",
"@angular/compiler-cli": "~16.2.12", "@angular/compiler-cli": "~16.2.12",
"@types/jasmine": "~3.8.0", "@types/jasmine": "~3.8.0",
"@types/node": "^12.11.1", "@types/node": "^12.20.55",
"jasmine-core": "~3.8.0", "jasmine-core": "~3.8.0",
"karma": "~6.3.0", "karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0", "karma-chrome-launcher": "~3.1.0",
@ -3646,7 +3646,8 @@
"version": "12.20.55", "version": "12.20.55",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
"dev": true "dev": true,
"license": "MIT"
}, },
"node_modules/@types/node-forge": { "node_modules/@types/node-forge": {
"version": "1.3.9", "version": "1.3.9",

View file

@ -36,7 +36,7 @@
"@angular/cli": "^16.2.9", "@angular/cli": "^16.2.9",
"@angular/compiler-cli": "~16.2.12", "@angular/compiler-cli": "~16.2.12",
"@types/jasmine": "~3.8.0", "@types/jasmine": "~3.8.0",
"@types/node": "^12.11.1", "@types/node": "^12.20.55",
"jasmine-core": "~3.8.0", "jasmine-core": "~3.8.0",
"karma": "~6.3.0", "karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0", "karma-chrome-launcher": "~3.1.0",

View file

@ -1,4 +0,0 @@
export const API_URL = 'http://127.0.0.1:3000';
export const WEBSOCK_URL = 'http://127.0.0.1:3000';
// export const API_URL = 'https://thanksgiving2023.ngweb.io/api';
//export const WEBSOCK_URL = "https://thanksgiving2023.ngweb.io/"

View file

@ -1,6 +1,5 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { io, Socket } from "socket.io-client"; import { io, Socket } from "socket.io-client";
import { API_URL, WEBSOCK_URL } from '../app.constants';
import { EventService } from "./services/event.service"; import { EventService } from "./services/event.service";
import {EventStateChanged, ServerEvent, VersusBeginEvent} from "../types/server-event"; import {EventStateChanged, ServerEvent, VersusBeginEvent} from "../types/server-event";
import { ApiService } from "./services/api.service"; import { ApiService } from "./services/api.service";
@ -11,6 +10,7 @@ import { VoiceService } from "./services/voice.service";
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import { getAudioPath } from "./helper/tts.helper"; import { getAudioPath } from "./helper/tts.helper";
import {animate, keyframes, style, transition, trigger} from "@angular/animations"; import {animate, keyframes, style, transition, trigger} from "@angular/animations";
import {environment} from "../environments/environment";
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -32,7 +32,7 @@ import {animate, keyframes, style, transition, trigger} from "@angular/animation
}) })
export class AppComponent implements OnInit, OnDestroy { export class AppComponent implements OnInit, OnDestroy {
title = 'thanksgiving'; title = 'thanksgiving';
connection = io(WEBSOCK_URL, { transports: ['websocket']}); connection = io(environment.WEBSOCK_URL, { transports: ['websocket']});
destroyed = new Subject<void>(); destroyed = new Subject<void>();
versusData: VersusBeginEvent|null = null; versusData: VersusBeginEvent|null = null;
audioSrc: string; audioSrc: string;
@ -55,6 +55,7 @@ export class AppComponent implements OnInit, OnDestroy {
}); });
this.apiService.getAppState('main').subscribe((result) => { this.apiService.getAppState('main').subscribe((result) => {
if(this.router.url.indexOf('admin') === -1) { if(this.router.url.indexOf('admin') === -1) {
console.log(this.router.url);
this.router.navigate([`/${result.value}`]).then(() => { this.router.navigate([`/${result.value}`]).then(() => {
console.log(`navigated to ${result.value}`); console.log(`navigated to ${result.value}`);
}) })

View file

@ -1,12 +1,11 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { EventService } from "../../services/event.service"; import { EventService } from "../../services/event.service";
import { filter, map } from "rxjs/operators"; import { filter, map } from "rxjs/operators";
import { EventCardPlayed } from "../../../types/server-event";
import { ApiService } from "../../services/api.service"; import { ApiService } from "../../services/api.service";
import { animate, style, transition, trigger } from "@angular/animations"; import { animate, style, transition, trigger } from "@angular/animations";
import { API_URL } from "../../../app.constants";
import { getAudioPath } from "../../helper/tts.helper"; import { getAudioPath } from "../../helper/tts.helper";
import { VoiceService } from "../../services/voice.service"; import { VoiceService } from "../../services/voice.service";
import {environment} from "../../../environments/environment";
@Component({ @Component({
selector: 'app-card-played', selector: 'app-card-played',
@ -59,7 +58,7 @@ export class CardPlayedComponent implements OnInit {
}) })
} }
getImageUrl() { getImageUrl() {
return `${API_URL}/guests/photo/${this.participantId}?$t=${this.imgTimestamp}`; return `${environment.API_URL}/guests/photo/${this.participantId}?$t=${this.imgTimestamp}`;
} }
getAudioSrc(text: string) { getAudioSrc(text: string) {

View file

@ -9,7 +9,7 @@ import { getAudioPath } from "../../helper/tts.helper";
}) })
export class GamePauseComponent implements OnInit, OnDestroy { export class GamePauseComponent implements OnInit, OnDestroy {
tstamp = new Date().getTime(); tstamp = new Date().getTime();
private interval: number; private interval: NodeJS.Timeout;
constructor(private voiceService: VoiceService) { } constructor(private voiceService: VoiceService) { }

View file

@ -4,9 +4,9 @@ import { EventService } from "../../services/event.service";
import { Observable, Subject, Subscription } from "rxjs"; import { Observable, Subject, Subscription } from "rxjs";
import { filter, map, takeUntil } from "rxjs/operators"; import { filter, map, takeUntil } from "rxjs/operators";
import { EventCardPlayed, EventCardsChanged, EventPhotosUpdated, ServerEvent } from "../../../types/server-event"; import { EventCardPlayed, EventCardsChanged, EventPhotosUpdated, ServerEvent } from "../../../types/server-event";
import { API_URL } from "../../../app.constants";
import { ApiService } from "../../services/api.service"; import { ApiService } from "../../services/api.service";
import { CardItem } from "../../../types/card-item"; import { CardItem } from "../../../types/card-item";
import {environment} from "../../../environments/environment";
@Component({ @Component({
selector: 'app-participant-item', selector: 'app-participant-item',
@ -74,7 +74,7 @@ export class ParticipantItemComponent implements OnInit, OnDestroy, OnChanges {
getImageUrl() { getImageUrl() {
if(this.participant) { if(this.participant) {
return `${API_URL}/guests/photo/${this.participant.telegramId}?$t=${this.imgTimestamp}`; return `${environment.API_URL}/guests/photo/${this.participant.telegramId}?$t=${this.imgTimestamp}`;
} }
return null; return null;
} }

View file

@ -1,9 +1,10 @@
import { API_URL } from "../../app.constants"; import {environment} from "../../environments/environment";
export function getAudioPath(text: string, voice: number = 1) { export function getAudioPath(text: string, voice: number = 1) {
return `${API_URL}/voice/tts?text=${text}&voice=${voice}`; return `${environment.API_URL}/voice/tts?text=${text}&voice=${voice}`;
} }
export function getAudioPathWithTemplate(path: string, text: string, vars: { [index: string]: string }) { export function getAudioPathWithTemplate(path: string, text: string, vars: { [index: string]: string }) {
const t = new Date().getTime(); const t = new Date().getTime();
return `${API_URL}/voice/${path}?text=${text}&vars=${JSON.stringify(vars)}&t=${t}`; return `${environment.API_URL}/voice/${path}?text=${text}&vars=${JSON.stringify(vars)}&t=${t}`;
} }

View file

@ -1,7 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http"; import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs"; import { Observable } from "rxjs";
import { API_URL } from "../../app.constants";
import { AppState } from "../../types/app-state"; import { AppState } from "../../types/app-state";
import { Participant } from "../../types/participant"; import { Participant } from "../../types/participant";
import { Question } from "../../types/question"; import { Question } from "../../types/question";
@ -12,6 +11,7 @@ import { PrizeDto } from "../../types/prize.dto";
import {QuestionresultsDto} from "../../types/questionresults.dto"; import {QuestionresultsDto} from "../../types/questionresults.dto";
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {VersusItem} from "../../types/versus-item"; import {VersusItem} from "../../types/versus-item";
import {environment} from "../../environments/environment";
export class FeatureFlagStateDto { export class FeatureFlagStateDto {
name: string; name: string;
@ -57,83 +57,85 @@ export interface EndgameResultsDto {
}) })
export class ApiService { export class ApiService {
constructor(private httpClient: HttpClient) { } constructor(private httpClient: HttpClient) {
console.log(environment.API_URL);
}
public getAppState(state: string): Observable<AppState> { public getAppState(state: string): Observable<AppState> {
return this.httpClient.get<AppState>(`${API_URL}/state/${state}`); return this.httpClient.get<AppState>(`${environment.API_URL}/state/${state}`);
} }
public getParticipants(): Observable<Participant[]> { public getParticipants(): Observable<Participant[]> {
return this.httpClient.get<Participant[]>(`${API_URL}/guests`); return this.httpClient.get<Participant[]>(`${environment.API_URL}/guests`);
} }
public getParticipant(id: number): Observable<Participant> { public getParticipant(id: number): Observable<Participant> {
return this.httpClient.get<Participant>(`${API_URL}/guests/${id}`); return this.httpClient.get<Participant>(`${environment.API_URL}/guests/${id}`);
} }
public getQuestion(): Observable<Question> { public getQuestion(): Observable<Question> {
return this.httpClient.get<Question>(`${API_URL}/quiz`); return this.httpClient.get<Question>(`${environment.API_URL}/quiz`);
} }
public setAppState(state: string, value: string) { public setAppState(state: string, value: string) {
return this.httpClient.post<AppState>(`${API_URL}/state`, { return this.httpClient.post<AppState>(`${environment.API_URL}/state`, {
state, state,
value value
}); });
} }
getCards(telegramId: number): Observable<CardItem[]> { getCards(telegramId: number): Observable<CardItem[]> {
return this.httpClient.get<CardItem[]>(`${API_URL}/cards/${telegramId}`); return this.httpClient.get<CardItem[]>(`${environment.API_URL}/cards/${telegramId}`);
} }
continueGame() { continueGame() {
console.log(`continue game`); console.log(`continue game`);
return this.httpClient.post(`${API_URL}/quiz/proceed`, {}); return this.httpClient.post(`${environment.API_URL}/quiz/proceed`, {});
} }
markQueueAsCompleted(_id: string) { markQueueAsCompleted(_id: string) {
return this.httpClient.post(`${API_URL}/game/${_id}/complete`, {}); return this.httpClient.post(`${environment.API_URL}/game/${_id}/complete`, {});
} }
pauseGame() { pauseGame() {
return this.httpClient.post(`${API_URL}/game/pause`, {}); return this.httpClient.post(`${environment.API_URL}/game/pause`, {});
} }
resumeGame() { resumeGame() {
return this.httpClient.post(`${API_URL}/game/resume`, {}); return this.httpClient.post(`${environment.API_URL}/game/resume`, {});
} }
getGameState() { getGameState() {
return this.httpClient.get<GameState>(`${API_URL}/game/state`); return this.httpClient.get<GameState>(`${environment.API_URL}/game/state`);
} }
getPenalty() { getPenalty() {
console.log(`get penalty`); console.log(`get penalty`);
return this.httpClient.get<PenaltyDto>(`${API_URL}/penalty`); return this.httpClient.get<PenaltyDto>(`${environment.API_URL}/penalty`);
} }
playExtraCards() { playExtraCards() {
console.log(`play extra cards`); console.log(`play extra cards`);
return this.httpClient.get(`${API_URL}/game/playextracards`); return this.httpClient.get(`${environment.API_URL}/game/playextracards`);
} }
getAdditionalQuestion(target: number) { getAdditionalQuestion(target: number) {
return this.httpClient.post<Question>(`${API_URL}/quiz/extraquestion`, { return this.httpClient.post<Question>(`${environment.API_URL}/quiz/extraquestion`, {
telegramId: target, telegramId: target,
}); });
} }
getImageUrl(id: number) { getImageUrl(id: number) {
const timestamp = new Date().getTime(); const timestamp = new Date().getTime();
return `${API_URL}/guests/photo/${id}?$t=${timestamp}}`; return `${environment.API_URL}/guests/photo/${id}?$t=${timestamp}}`;
} }
getPrize(): Observable<PrizeDto> { getPrize(): Observable<PrizeDto> {
return this.httpClient.get<PrizeDto>(`${API_URL}/gifts`); return this.httpClient.get<PrizeDto>(`${environment.API_URL}/gifts`);
} }
getQuestionResults() { getQuestionResults() {
return this.httpClient.get<QuestionresultsDto[]>(`${API_URL}/quiz/question-results`).pipe(map((data) => return this.httpClient.get<QuestionresultsDto[]>(`${environment.API_URL}/quiz/question-results`).pipe(map((data) =>
data.map((item) => { data.map((item) => {
return { return {
...item, ...item,
@ -144,29 +146,29 @@ export class ApiService {
} }
getFeatureFlagState(feature: string) { getFeatureFlagState(feature: string) {
return this.httpClient.get<FeatureFlagStateDto>(`${API_URL}/featureflag/${feature}`); return this.httpClient.get<FeatureFlagStateDto>(`${environment.API_URL}/featureflag/${feature}`);
} }
setFeatureFlagState(feature: string, state: boolean) { setFeatureFlagState(feature: string, state: boolean) {
return this.httpClient.post<FeatureFlagStateDto>(`${API_URL}/featureflag`, { name: feature, state: state }); return this.httpClient.post<FeatureFlagStateDto>(`${environment.API_URL}/featureflag`, { name: feature, state: state });
} }
getStateDetails() { getStateDetails() {
return this.httpClient.get<ConfigRecordDto>(`${API_URL}/game/state-details`); return this.httpClient.get<ConfigRecordDto>(`${environment.API_URL}/game/state-details`);
} }
getVersus() { getVersus() {
return this.httpClient.get<VersusItem>(`${API_URL}/versus`); return this.httpClient.get<VersusItem>(`${environment.API_URL}/versus`);
} }
completeVersus(winner: number, loser: number) { completeVersus(winner: number, loser: number) {
return this.httpClient.post(`${API_URL}/versus/complete`, { return this.httpClient.post(`${environment.API_URL}/versus/complete`, {
winner: winner, winner: winner,
loser: loser loser: loser
}); });
} }
getEndgameResults() { getEndgameResults() {
return this.httpClient.get<EndgameResultsDto>(`${API_URL}/quiz/endgame-results`) return this.httpClient.get<EndgameResultsDto>(`${environment.API_URL}/quiz/endgame-results`)
} }
} }

View file

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http"; import {HttpClient} from "@angular/common/http";
import {API_URL} from "../../app.constants"; import {environment} from "../../environments/environment";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -10,26 +10,26 @@ export class TestingApiService {
constructor(private httpClient: HttpClient) { } constructor(private httpClient: HttpClient) { }
public simulateVersus() { public simulateVersus() {
return this.httpClient.post(`${API_URL}/versus/simulate-versus`, {}); return this.httpClient.post(`${environment.API_URL}/versus/simulate-versus`, {});
} }
resetAllVersusTasksAsIncompleted() { resetAllVersusTasksAsIncompleted() {
return this.httpClient.post(`${API_URL}/versus/reset-all`, {}); return this.httpClient.post(`${environment.API_URL}/versus/reset-all`, {});
} }
resetAllPlayersScore() { resetAllPlayersScore() {
return this.httpClient.post(`${API_URL}/guests/reset-score`, {}); return this.httpClient.post(`${environment.API_URL}/guests/reset-score`, {});
} }
clearGameQueue() { clearGameQueue() {
return this.httpClient.post(`${API_URL}/game/clear-queue`, {}); return this.httpClient.post(`${environment.API_URL}/game/clear-queue`, {});
} }
simulateEndGamePoints() { simulateEndGamePoints() {
return this.httpClient.post(`${API_URL}/quiz/calculate-endgame-extrapoints`, {}) return this.httpClient.post(`${environment.API_URL}/quiz/calculate-endgame-extrapoints`, {})
} }
simulateValidAnswer() { simulateValidAnswer() {
return this.httpClient.post(`${API_URL}/game/simulate-valid-answer`, {}); return this.httpClient.post(`${environment.API_URL}/game/simulate-valid-answer`, {});
} }
} }

View file

@ -1,10 +1,10 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http"; import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http";
import { API_URL } from "../../app.constants";
import {delay, delayWhen, interval, Observable, of, Subject} from "rxjs"; import {delay, delayWhen, interval, Observable, of, Subject} from "rxjs";
import {ApiService} from "./api.service"; import {ApiService} from "./api.service";
import {takeUntil, tap} from "rxjs/operators"; import {takeUntil, tap} from "rxjs/operators";
import {SharedMethods} from "../shared/sharedmethods"; import {SharedMethods} from "../shared/sharedmethods";
import {environment} from "../../environments/environment";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -45,11 +45,11 @@ export class VoiceService {
} }
getAudioUrl(text: string,voice: number = 1) { getAudioUrl(text: string,voice: number = 1) {
return `${API_URL}/voice/tts?voice=${voice}&text=${text}` return `${environment.API_URL}/voice/tts?voice=${voice}&text=${text}`
} }
getAudioUrlSSML(text: string) { getAudioUrlSSML(text: string) {
return `${API_URL}/voice/ssml?text=${encodeURI(text)}` return `${environment.API_URL}/voice/ssml?text=${encodeURI(text)}`
} }
audioEnded() { audioEnded() {

View file

@ -22,11 +22,11 @@
<p class="card-text">Если тебе требуется пояснять эту карточку - то игра не для тебя, налей себе алкоголь и побольше.</p> <p class="card-text">Если тебе требуется пояснять эту карточку - то игра не для тебя, налей себе алкоголь и побольше.</p>
</div> </div>
</div> </div>
<div class="card text-white bg-secondary mb-3" style="max-width: 18rem;" #shitCard> <div class="card text-white bg-secondary mb-3" style="max-width: 18rem;" #versusCard>
<img src="../../../assets/cards/ShitCard.png" class="card-img-top" alt="..."> <img src="../../../assets/cards/VersusCard.png" class="card-img-top" alt="...">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Говнокарта</h5> <h5 class="card-title">Поединок</h5>
<p class="card-text">Можно подкинуть еще один вопрос игроку, который правильно ответил.</p> <p class="card-text">Можно вызвать другого игрока на схватку 1 на 1 в мини-игре</p>
</div> </div>
</div> </div>
<div class="card text-white bg-success mb-3" style="max-width: 18rem;" #luckyCard> <div class="card text-white bg-success mb-3" style="max-width: 18rem;" #luckyCard>

View file

@ -33,7 +33,7 @@ interface RuleItem {
export class OnboardingComponent implements OnInit, OnDestroy { export class OnboardingComponent implements OnInit, OnDestroy {
@ViewChild('avoidPenaltyCard') private avoidPenaltyCardEl: ElementRef; @ViewChild('avoidPenaltyCard') private avoidPenaltyCardEl: ElementRef;
@ViewChild('stolePrizeCard') private stolePrizeCardEl: ElementRef; @ViewChild('stolePrizeCard') private stolePrizeCardEl: ElementRef;
@ViewChild('shitCard') private shitCardEl: ElementRef; @ViewChild('versusCard') private versusCardEl: ElementRef;
@ViewChild('luckyCard') private luckyCardEl: ElementRef; @ViewChild('luckyCard') private luckyCardEl: ElementRef;
@ViewChild('banPlayerCard') private banPlayerEl: ElementRef; @ViewChild('banPlayerCard') private banPlayerEl: ElementRef;
@ViewChild('doubleTreasureCard') private doubleTreasureCardEl: ElementRef; @ViewChild('doubleTreasureCard') private doubleTreasureCardEl: ElementRef;
@ -42,24 +42,19 @@ export class OnboardingComponent implements OnInit, OnDestroy {
{ text: 'Вопросы и ответы будут отображаться на экране и в Боте Благодарения.' }, { text: 'Вопросы и ответы будут отображаться на экране и в Боте Благодарения.' },
{ text: 'Каждый игрок в начале игры имеет на руках 4 карты, набор карт определяется случайно. Описание карт ты найдешь ниже. После использования карты ты получаешь новую случайную карту.' }, { text: 'Каждый игрок в начале игры имеет на руках 4 карты, набор карт определяется случайно. Описание карт ты найдешь ниже. После использования карты ты получаешь новую случайную карту.' },
{ text: 'На разыгрывание карты время ограничено, примерно 10 секунд.' }, { text: 'На разыгрывание карты время ограничено, примерно 10 секунд.' },
{ text: 'Задача игрока - ответить правильно и быстрее других.' }, { text: 'Вы долго просили оптимизировать геймплей для медленных и глупых, и мы это сделали!'},
{ text: 'Первый игрок, ответивший правильно, получает одно очко и шанс выиграть приз.' }, { text: 'Задача игрока - ответить правильно и быстрее других, ну или хотя бы просто правильно в течение 20 секунд' },
{ text: 'Приз??? Какой приз?', screpa: true, voice: 2 }, { text: 'Первый игрок, ответивший правильно, получает два очка' },
{ text: 'Я не думаю, что их мозгов хватит для получения призов', screpa: true, voice: 2 }, { text: 'Все остальные, ответившие правильно, получают одно очко'},
{ text: 'А ты вообще кто такая?', hideWithoutVoice: true }, { text: 'Иногда за неправильные ответы игроки будут получать наказания' },
{ text: 'Ах, да.. простите, забыла представиться, я - Скрепа по фамилии Духовная', screpa: true, voice: 2},
{ text: 'И на кой ты нам нужна?', hideWithoutVoice: true },
{ text: 'Я тут, чтобы нарушать ход игры, и вообще тебя не спрашивали. ', screpa: true, voice: 2},
{ text: '[Ладно, ]В общем - чем больше правильных ответов - тем больше призов '},
{ text: 'Первый игрок, ответивший неправильно, получает наказание, и мы переходим к следующему вопросу' },
{ text: 'Избежать наказания можно только с помощью соотвествуещей карты, данную карту ты можешь сыграть перед озвучиванием наказания', action: () => { { text: 'Избежать наказания можно только с помощью соотвествуещей карты, данную карту ты можешь сыграть перед озвучиванием наказания', action: () => {
this.shakeCard(this.avoidPenaltyCardEl); this.shakeCard(this.avoidPenaltyCardEl);
}}, }},
{ text: 'Карту "украсть приз" ты можешь сыграть в момент, когда кто-то собирается получить награду, но до момента того, как ты узнаешь, что это именно за приз', action: () => { { text: 'Карту "украсть приз" ты можешь сыграть в момент, когда кто-то собирается получить награду, но до момента того, как ты узнаешь, что это именно за приз', action: () => {
this.shakeCard(this.stolePrizeCardEl); this.shakeCard(this.stolePrizeCardEl);
}}, }},
{ text: '"Говно-карту" ты можешь разыграть в момент, когда кто-то ответил правильно, тем самым ты заставишь именно этого игрока ответить на один дополнительный вопрос. На одного игрока можно сыграть неограниченное количество этих карт', action: () => { { text: 'Карту "Поединок" ты можешь разыграть в любой момент, чтобы вызвать игрока на дуэль', action: () => {
this.shakeCard(this.shitCardEl); this.shakeCard(this.versusCardEl);
}}, }},
{ text: '"Лаки карту" ты сможешь сыграть после своего правильного ответа, она увеличит твои шансы на получение приза', action: () => { { text: '"Лаки карту" ты сможешь сыграть после своего правильного ответа, она увеличит твои шансы на получение приза', action: () => {
this.shakeCard(this.luckyCardEl); this.shakeCard(this.luckyCardEl);
@ -78,22 +73,10 @@ export class OnboardingComponent implements OnInit, OnDestroy {
}, },
{ text: 'Не торопись с ответами, игра идет до той поры, пока мы не разыграем все призы' }, { text: 'Не торопись с ответами, игра идет до той поры, пока мы не разыграем все призы' },
{ {
text: 'Ах да, так как создатель игры, работает на Microsoft, мы добавили привычные вам баги, сейчас расскажу', text: 'Ах да, так как создатель игры, работает на Microsoft, мы добавили привычные вам баги, но все их оставим в секрете',
screpa: true,
voice: 2
}, },
{ {
text: 'Если у вас нет вариантов ответа - перезайдите в бот или перезапустите телеграмм', text: 'Кажется, правила закончились'
screpa: true,
voice: 2,
},
{
text: 'Остальные баги будут сюрпризом! Но не забывайте громко кричать, когда что-то работает не так',
screpa: true,
voice: 2,
},
{
text: 'Кажется правила закончились'
} }
]; ];
@ -172,7 +155,7 @@ export class OnboardingComponent implements OnInit, OnDestroy {
this.allRulesAnnounced = true; this.allRulesAnnounced = true;
this.voiceService.playAudio(getAudioPath(`Это все правила, надеюсь, все понятно. А если нет - сейчас Кирилл и Оксана вам все пояснят, this.voiceService.playAudio(getAudioPath(`Это все правила, надеюсь, все понятно. А если нет - сейчас Кирилл и Оксана вам все пояснят,
ну и совсем для тупых - пустила по кругу правила на экране, ну и совсем для тупых - пустила по кругу правила на экране,
а если ты их не поймешь - то за Путина голосовать пойдешь (или за Грузинскую мечту) . Каждый правильный ответ отнимает у Путина год жизни, постарайтесь!`)); а если ты их не поймешь - то очень жаль тебя глупенького`));
this.voiceService.audioEndedSubject.pipe(takeUntil(this.destroyed$),take(1)).subscribe(() => { this.voiceService.audioEndedSubject.pipe(takeUntil(this.destroyed$),take(1)).subscribe(() => {
setInterval(() => { this.playNextRule() }, 6000); setInterval(() => { this.playNextRule() }, 6000);
this.currentRulePosition = 0 this.currentRulePosition = 0

View file

@ -1,3 +1,5 @@
export const environment = { export const environment = {
production: true production: true,
API_URL: "https://thanksgiving2024.ngweb.io/api",
WEBSOCK_URL: "https://thanksgiving2024.ngweb.io"
}; };

View file

@ -3,7 +3,9 @@
// The list of file replacements can be found in `angular.json`. // The list of file replacements can be found in `angular.json`.
export const environment = { export const environment = {
production: false production: false,
API_URL: "http://localhost:3000",
WEBSOCK_URL: "http://localhost:3000"
}; };
/* /*

View file

@ -3,7 +3,7 @@
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "./out-tsc/app", "outDir": "./out-tsc/app",
"types": [] "types": ["node"]
}, },
"files": [ "files": [
"src/main.ts", "src/main.ts",