import { PlayTTSService } from 'src/app/services/play-tts.service';
import { ChangeDetectorRef } from "@angular/core";
import { AccountService } from "../services/account.service";
import { CabriDataService } from "../services/cabri-data.service";
import { GlobalService } from "../services/global.service";
import { Phrase } from "./phrase";
import { Scenario } from "./scenario";
import { ScenarioPhrase } from "./scenario-phrase";
import { Tutorial } from "./tutorial";
import { ScenarioCabri } from './scenario-cabri';
import { ReplaySubject } from 'rxjs';
export class ScenarioMap extends ScenarioCabri {
randomIndex: number;
currentPhrase: {index: number, type: string};
constructor(
cabri: CabriDataService,
accountService: AccountService,
globalService: GlobalService,
page: any,
cd: ChangeDetectorRef,
public ttsService: PlayTTSService
) {
super(cabri, accountService, globalService, page, cd, ttsService);
this.currentPhrase = {index: 0, type: undefined};
}
/**
* Runs a tutorial tour to present to the user the different inputMethods of the activity (2 versions: with microphone plugged or not)
* @ignore
*/
runMathiaSpeech(content: Array<any>, type?: string): Promise<void> {
const p = new Promise<void>((resolve, reject) => {
this.globalService.mathiaSpeechRunning = true;
this.cabriService.allowInputMethodChange = false;
let lastElement;
const contentClone = content.slice(0);
contentClone.reverse().forEach(element => {
const current = new Tutorial();
current.phrase = element.phrase;
if (element.phraseTTS) {
current.phraseTTS = element.phraseTTS;
}
if (element.onlySpeech) {
current.onlySpeech = element.onlySpeech;
}
if (element.randomSpeechMode) {
current.randomSpeechMode = element.randomSpeechMode;
}
if (element.textBubble) {
current.textBubble = element.textBubble;
}
if (element.buttons) {
current.buttons = element.buttons;
}
if (element.disableSkip) {
current.disableSkip = element.disableSkip;
}
if (element.buttonText) {
current.buttonText = element.buttonText;
}
if (element.shootingStar) {
current.shootingStar = element.shootingStar;
}
if (element.normalStar) {
current.normalStar = element.normalStar;
}
if (element.moon) {
current.moon = element.moon;
}
if (!lastElement) {
current.callback = async () => {
// if (this.globalService.onActivityPage) {
if (typeof element.callback === "function" && !this.lockCallback) {
await element.callback();
}
// this.award = "none";
// this.detectChanges();
// } else {
// resolve();
// }
this.globalService.mathiaSpeechRunning = false;
// console.log("runMathiaSpeech END");
this.skipSequence = false;
resolve();
};
} else {
current.callback = async () => {
// if (this.globalService.onActivityPage) {
if (typeof element.callback === "function" && !this.lockCallback) {
await element.callback();
}
// } else {
// resolve();
// }
};
}
current.next = lastElement;
lastElement = current;
});
if (this.lockCallback) {
// console.error("rejected by lockCallback");
reject();
} else {
this.runMathiaSpeechCore(lastElement, type);
}
});
this.currentRunMathiaSpeechPromise.push({promise: p, scenario: content});
return p;
}
randomIndexWithoutRepeat(phrase: Phrase[]): Promise<number> {
return new Promise(resolve => {
const int = setInterval(() => {
const randomIndex: number = Math.floor(Math.random() * phrase.length);
if (this.randomIndex !== randomIndex) {
clearInterval(int);
resolve(randomIndex);
}
}, 10);
});
}
incrementalIndex(phrase: Phrase[], phraseType?: string): Promise<number> {
return new Promise(resolve => {
if (this.currentPhrase.index < phrase.length - 1 && !(phraseType === undefined || this.currentPhrase?.type != phraseType)) {
this.currentPhrase = {index: this.currentPhrase.index + 1, type: phraseType};
resolve(this.currentPhrase.index);
} else {
this.currentPhrase = {index: 0, type: phraseType};
resolve(this.currentPhrase.index);
}
});
}
/**
* @ignore
*/
runMathiaSpeechCore(tutorial: Tutorial, type?: string): Promise<void> {
return new Promise(async (resolve, reject) => {
// if (this.globalService.onActivityPage) {
if (tutorial) {
if (Array.isArray(tutorial.phrase) && tutorial.phrase.length > 1) {
if (tutorial.randomSpeechMode) {
// select random index from tutorial.phrase array
// const index = await this.randomIndexWithoutRepeat(tutorial.phrase);
// or incremental index:
const index = await this.incrementalIndex(tutorial.phrase, type);
// TODO: implement incremental mode as an option?
// console.log("random index = ${randomIndex);
tutorial.phrase = tutorial.phrase[index];
if (tutorial.phraseTTS) {
tutorial.phraseTTS = tutorial.phraseTTS[index];
}
} else {
// increment index of tutorial.phrase array
this.mscPhraseArrayIndex++;
if (this.mscPhraseArrayIndex >= tutorial.phrase.length) {
this.mscPhraseArrayIndex = 0;
}
// console.log("tutorial.phrase = ", tutorial.phrase);
// console.log("this.mscPhraseArrayIndex = ${this.mscPhraseArrayIndex);
tutorial.phrase = tutorial.phrase[this.mscPhraseArrayIndex];
if (tutorial.phraseTTS) {
tutorial.phraseTTS = tutorial.phraseTTS[this.mscPhraseArrayIndex];
}
}
} else if (Array.isArray(tutorial.phrase) && tutorial.phrase.length === 1) {
tutorial.phrase = tutorial.phrase[0];
if (tutorial.phraseTTS) {
tutorial.phraseTTS = tutorial.phraseTTS[0];
}
}
if (tutorial.textBubble === true) {
if (tutorial.buttons === true) {
this.page.mathiaSpeechButtonText = tutorial.buttonText;
this.page.award = "validation_misc";
// console.log(`this.page.mathiaSpeechButtonText = ${this.page.mathiaSpeechButtonText}`);
} else {
this.page.award = "simpleMessage";
}
if (tutorial.disableSkip) {
this.page.award = "simpleMessageNoSkip";
}
if (tutorial.shootingStar) {
this.page.award = "simpleMessageShootingStar";
}
if (tutorial.normalStar) {
this.page.award = "simpleMessageNormalStar";
}
if (tutorial.moon) {
this.page.award = "simpleMessageMoon";
}
} else {
this.page.award = "none";
}
this.lastPhrase = tutorial.phrase;
if (!tutorial.onlySpeech) {
this.page.displayCM = true;
}
if (!this.skipSequence && this.cd) {
this.detectChanges();
}
if (!this.skipSequence && !this.lockCallback) {
this.ttsService.playTTSEventProtected(tutorial, async () => {
tutorial.callback().then(() => {
this.page.mathiaSpeechButtonText = null;
if (!this.page.menuOpen && !this.globalService.appIdle) {
this.page.eventMessage?.next(tutorial.phrase);
this.detectChanges();
return this.runMathiaSpeechCore(tutorial.next, type);
} else {
this.page.eventMessage?.next(tutorial.phrase);
this.detectChanges();
this.tutoCallbackSave = tutorial.next;
}
});
});
} else if (this.skipSequence === true && !this.lockCallback) {
tutorial.callback().then(async () => {
this.page.mathiaSpeechButtonText = null;
if (!this.page.menuOpen && !this.globalService.appIdle) {
return this.runMathiaSpeechCore(tutorial.next, type);
} else {
this.detectChanges();
this.tutoCallbackSave = tutorial.next;
}
});
}
}
// }
});
}
async allValidated() {
const speechSequence = [
new ScenarioPhrase($localize`Bravo ${this.accountService.team[0].name}:playerName: ! Tu as fini l’aventure !`),
// new ScenarioPhrase($localize`Enfin... Pour l’instant ! Car cette histoire continuera bientôt !`),
new ScenarioPhrase($localize`Je suis vraiment fière de toi ! Quel chemin nous avons parcouru !`),
new ScenarioPhrase($localize`Tu peux maintenant refaire les missions de ton choix pour essayer d’améliorer ton score.`),
new ScenarioPhrase($localize`Tu peux aussi faire des missions spéciales en cliquant ici !`, async () => {
this.page.displayBonusLevels = true;
if (!this.globalService.lowPerformanceMode) {
this.page.playBonusLevelsAnim = true;
}
this.page.detectChanges();
await this.page.timeOut(2000);
}),
new ScenarioPhrase($localize`A toi de jouer !`, async () => {
this.page.playBonusLevelsAnim = false;
this.page.detectChanges();
}),
];
await this.runMathiaSpeech(speechSequence, "allValidated");
}
async mapMove(levelUnLocked = false) {
let speechSequence;
let type: string;
if (levelUnLocked) {
type = "mapMoveUnlocked";
if (this.accountService.team && this.accountService.team.length === 1) {
speechSequence = [
new ScenarioPhrase(
[
$localize`Allons-y ${this.accountService.team[0].name}:playerName: !`,
$localize`Décollage !`,
$localize`Qu’y a t-il par ici ?`,
$localize`Et par là ?`,
$localize`En route !`,
$localize`Et si nous faisions celui-ci ?`,
$localize`Très bien, allons voir par là !`,
$localize`Dacodac...`,
$localize`Dur de choisir, pas vrai ?`,
$localize`Let’s go !`,
$localize`Plus vite que la lumière !`,
$localize`Allons-voir là-bas !`,
$localize`Ici ?`,
$localize`Tu es de nature indécise toi, non ?`,
$localize`Quelle épopée !`,
$localize`Allumage des réacteurs !`,
$localize`Allons-y ${this.accountService.team[0].name}:playerName: ! Une mission nous attend !`,
$localize`Appuie sur le bouton jouer pour lancer une mission !`
],
async () => {}
).setRandomMode()
];
} else {
speechSequence = [
new ScenarioPhrase(
[
$localize`Allons-y !`,
$localize`Qu’y a t-il par ici ?`,
$localize`Décollage !`,
$localize`Et par là ?`,
$localize`En route !`,
$localize`Et si nous faisions celui-ci ?`,
$localize`Très bien, allons voir par là !`,
$localize`Dacodac...`,
$localize`Ici ?`,
$localize`Dur de choisir, pas vrai ?`,
$localize`Let’s go !`,
$localize`Plus vite que la lumière !`,
$localize`Tu es de nature indécise toi, non ?`,
$localize`Quelle épopée !`,
$localize`Allumage des réacteurs !`,
$localize`Allons-y ! Une mission nous attend !`,
$localize`Appuie sur le bouton jouer pour lancer une mission !`
],
async () => {}
).setRandomMode()
];
}
} else {
type = "mapMovelocked";
speechSequence = [
new ScenarioPhrase([
$localize`Oups! On dirait que cette mission n’est pas encore disponible !`,
$localize`Celle-là non plus ! Il faut que tu termines les missions précédentes pour y accéder !`,
$localize`Allons faire la mission qui est dévérouillée ! Elle a une lumière verte !`,
],
async () => {}
).setRandomMode()
];
}
await this.runMathiaSpeech(speechSequence, type);
}
}