File

src/app/models/scenario-ose.ts

Constructor

constructor(accountService: AccountService, globalService: GlobalService, oseJourneyService: OseJourneyService, page: any, cd: ChangeDetectorRef, ttsService: any)

Methods

runMathiaSpeech
runMathiaSpeech(content: any[], globalBubble: boolean)

Runs a tutorial tour to present to the user the different inputMethods of the activity (2 versions: with microphone plugged or not)

Returns: any
runMathiaSpeechCore
runMathiaSpeechCore(tutorial: Tutorial)
Returns: void
waitResolveFromOutside
waitResolveFromOutside()

creates a Promise to be awaited and resolved from outside if not in skipSequence mode
used in createSpeechSequenceFromFicheFeedback()

Returns: any
launchFeedbackWithEnd
launchFeedbackWithEnd(feedbackHtml: string, globalBubble: boolean)

Read of feedback at the end of the activity

Returns: void
readSpeechSequenceFromFicheContent
readSpeechSequenceFromFicheContent(scenarios: TTSContent[])

convert TTSContent array from fiche & build / read a speechSequence for runMathiaSpeech
autoplays video
splits

with punctuation

Returns: void
splitTextPunctationToScenarioPhraseArray
splitTextPunctationToScenarioPhraseArray(text: string)

splits given text depending on punctuation and returns a SpeechSequence array

Returns: void

Properties

Protected oseJourneyService
oseJourneyService: OseJourneyService
previousTitleRead
previousTitleRead: string
Public resolveScenarioCallbackFromOutside
resolveScenarioCallbackFromOutside: () => void
Public resolveTimeoutCancelable
resolveTimeoutCancelable: (value: any) => void
ttsService
ttsService: any
import { PlayTTSService } from "src/app/services/play-tts.service";
import { TTSContent, ContentTagNames } from "./fiche";
import { ChangeDetectorRef, QueryList } from "@angular/core";
import { AccountService } from "../services/account.service";
import { GlobalService } from "../services/global.service";
import { ScenarioPhrase } from "./scenario-phrase";
import { Tutorial } from "./tutorial";
import { FicheComponent } from "../components/fiche/fiche.component";
import { OseExerciceType } from "./ose2-journey";
import { OseJourneyService } from "../services/ose-journeys.service";
import { Scenario } from "./scenario";
import { ReplaySubject } from "rxjs";
export class ScenarioOse extends Scenario {
	protected oseJourneyService: OseJourneyService;
	public resolveTimeoutCancelable: (value: unknown) => void;
	public resolveScenarioCallbackFromOutside: () => void;
	previousTitleRead: string;

	constructor(
		accountService: AccountService,
		globalService: GlobalService,
		oseJourneyService: OseJourneyService,
		page: any,
		cd: ChangeDetectorRef,
		public ttsService: PlayTTSService
	) {
		super(accountService, globalService, page, cd, ttsService);
		this.oseJourneyService = oseJourneyService;
	}

	/**
	 * 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: any[], globalBubble?: boolean): Promise<void> {
		
		const p = new Promise<void>((resolve, reject) => {
			console.log("runMathiaSpeech entered");
			this.globalService.mathiaSpeechRunning = true;
			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 (element.keepBubble) {
					current.keepBubble = element.keepBubble;
				}
				//array read in reverse so the first tutorial is the end and need to resolve
				if (!lastElement) {
					current.callback = async () => {
						if (element.callback) {
							if (typeof element.callback === "function" && !this.lockCallback) {
								try {
									await element.callback();
								} catch (e) {
									console.error("catch callback", e);
								}
							}
						}
						this.globalService.mathiaSpeechRunning = false;
						this.skipSequence = false;
						resolve();
					};
				} else {
					current.callback = async () => {
						if (element.callback) {
							if (typeof element.callback === "function" && !this.lockCallback) {
								try {
									await element.callback();
								} catch (e) {
									console.error("catch callback", e);
								}
							}
						}
					};
				}
				current.next = lastElement;
				lastElement = current;
			});
			if (this.lockCallback) {
				// console.error("rejected by lockCallback");
				reject();
			} else {
				this.runMathiaSpeechCore(lastElement);
			}
		});

		this.currentRunMathiaSpeechPromise.push({promise: p, scenario: content});
		return p;
	}

	/**
	 * @ignore
	 */
	runMathiaSpeechCore(tutorial: Tutorial): void {
		if (tutorial) {
			if (Array.isArray(tutorial.phrase) && tutorial.phrase.length > 1) {
				if (tutorial.randomSpeechMode) {
					// select random index from tutorial.phrase array
					const randomIndex = Math.floor(Math.random() * tutorial.phrase.length);
					// console.log("random index = " + randomIndex);oe
					tutorial.phrase = tutorial.phrase[randomIndex];
					if (tutorial.phraseTTS) {
						tutorial.phraseTTS = tutorial.phraseTTS[randomIndex];
					}
				} else {
					// increment index of tutorial.phrase array
					this.mscPhraseArrayIndex++;
					if (this.mscPhraseArrayIndex >= tutorial.phrase.length) {
						this.mscPhraseArrayIndex = 0;
					}
					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];
				}
			}
			this.page?.eventMessage?.next(tutorial.phrase);
			this.lastPhrase = tutorial.phrase;
			if (!tutorial.onlySpeech && this.page?.displayTTSBubble) {
				this.page.displayTTSBubble = true;
			}
			if (!this.skipSequence && this.cd) {
				this.detectChanges();
			}
			if (!this.skipSequence && !this.lockCallback) {
				if (this.page?.injectTextToBubble) {
					this.page.injectTextToBubble(tutorial.phrase);
				}
				this.ttsService.playTTSEventProtected(tutorial, async () => {
					tutorial.callback().then(() => {
						this.page.mathiaSpeechButtonText = null;
						if (!this.page.menuOpen && !this.globalService.appIdle) {
							this.detectChanges();
							return this.runMathiaSpeechCore(tutorial.next);
						} else {
							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);
					} else {
						this.detectChanges();
						this.tutoCallbackSave = tutorial.next;
					}
				});
			}
		}
	}

	

	/**
	 * creates a Promise to be awaited and resolved from outside if not in skipSequence mode
	 * used in createSpeechSequenceFromFicheFeedback()
	 * @ignore
	 */
	async waitResolveFromOutside(): Promise<void> {
		return new Promise(async resolve => {
			console.error("waitResolveFromOutside enter ");
			if (!this.skipSequence && !this.page.ficheSkipped) {
				this.resolveScenarioCallbackFromOutside = resolve;
			} else {
				this.resolveScenarioCallbackFromOutside = null;
				resolve();
			}
		});
	}

	/**
	 * Read of feedback at the end of the activity
	 */
	async launchFeedbackWithEnd(feedbackHtml: string, globalBubble = true) {
		const speechSequence = new Array();
		if (feedbackHtml && feedbackHtml != "") {
			await this.readHTML(feedbackHtml, globalBubble);
		} else {
			if (this.globalService.onActivityPage) {
				switch (this.globalService.activityRunningName) {
					case OseExerciceType.fiche:
						break;
					case OseExerciceType.memory:
						speechSequence.push(new ScenarioPhrase($localize`Bravo tu as trouvé toutes les paires`));
						break;
					case OseExerciceType.quizz:
						break;
					case OseExerciceType.coloriage:
						speechSequence.push(new ScenarioPhrase($localize`Bravo tu as terminé le coloriage`));
						break;
					case OseExerciceType.puzzle:
						speechSequence.push(new ScenarioPhrase($localize`Bravo tu as bien reconstruit l’image`));
						break;
					case OseExerciceType.spotDifference:
						speechSequence.push(new ScenarioPhrase($localize`Bravo tu as réussi à trouver toutes les erreurs présentes dans l’image`));
						break;
				}
			}
		}
		if (this.globalService.onActivityPage && this.oseJourneyService.currentJourney) {
			speechSequence.push(new ScenarioPhrase($localize`Appuie sur le bouton en bas à droite pour passer à la prochaine activité.`));
		}

		if (speechSequence && speechSequence.length > 0) {
			await this.runMathiaSpeech(speechSequence, globalBubble);
		}
	}
	/**
	 * convert TTSContent array from fiche & build / read a speechSequence for runMathiaSpeech
	 * autoplays video
	 * splits <p> with punctuation
	 */
	async readSpeechSequenceFromFicheContent(scenarios: TTSContent[]) {
		// console.error(JSON.stringify(scenarios));
		await this.globalService.speechBubbleComponent.displayGlobalBubble(false);
		let vimeoPresent = false;
		const speechSequence = new Array();
		const videoPlayerScenario = new Array()
		scenarios?.forEach((scenario: TTSContent) => {
			if (scenario) {
				if (scenario.tag === ContentTagNames.H1) {
					speechSequence.push(new ScenarioPhrase([scenario.text]));
				}
				if (scenario.tag === ContentTagNames.H2) {
					if (this.previousTitleRead !== scenario.text) {
						speechSequence.push(new ScenarioPhrase([scenario.text]));
						this.previousTitleRead = scenario.text;
					}
				}
				if (scenario.tag === ContentTagNames.H3) {
					speechSequence.push(new ScenarioPhrase([scenario.text]));
				}
				if (scenario.tag === ContentTagNames.P) {
					const scenarioPhraseArray = this.splitTextPunctationToScenarioPhraseArray(scenario.text);
					scenarioPhraseArray.forEach(scenarioPhrase => {
						speechSequence.push(scenarioPhrase);
					});
				}
				if (scenario.tag === ContentTagNames.AUDIO) { }
				if (scenario.tag === ContentTagNames.VIDEO_VIMEO) {
					vimeoPresent = true;
					videoPlayerScenario.push(
						new ScenarioPhrase([" "], async () => {
							if (!this.skipSequence) {
								await this.page.ficheComponent.vimeoFirstVideoLoaded;
								if (
									(this.page.ficheComponent as FicheComponent).vimeoPlayers &&
									(this.page.ficheComponent as FicheComponent).vimeoPlayers.length > 0
								) {
									(this.page.ficheComponent as FicheComponent).vimeoPlayers[0].play();
									setTimeout(() => {
										if (this.page.ficheComponent) {
											(this.page.ficheComponent as FicheComponent).animateNextButton = true;
										}
									}, 3000);
								}
							}
						})
					);
					if (this.globalService.muteSounds) {
						speechSequence.push(...videoPlayerScenario);
					}
				}
				if (scenario.tag === ContentTagNames.VIDEO_WP) {
				}
				if (scenario.tag === ContentTagNames.IMG) {
				}
			}
		});
		if (!vimeoPresent) {
			speechSequence.push(
				new ScenarioPhrase([" "], async () => {
					if (this.page.ficheComponent) {
						(this.page.ficheComponent as FicheComponent).animateNextButton = true;
					}
				})
			);
		} else if (!this.globalService.muteSounds) {
			speechSequence.push(...videoPlayerScenario)
		}
		if(this.globalService.muteSounds){
			if (this.page.ficheComponent) {
				(this.page.ficheComponent as FicheComponent).animateNextButton = true;
			}
		}

		await this.runMathiaSpeech(speechSequence);
	}

	/**
	 * splits given text depending on punctuation and returns a SpeechSequence array
	 */
	splitTextPunctationToScenarioPhraseArray(text: string) {
		const speechSequence = [];
		if (text.match(/(\.|\?|\!)/g)) {
			// Split feedback with punctuation:
			const feedbackSequence = text.split(/(\.|\?|\!)/g);
			// move punctuation index content to the end of the previous index:
			feedbackSequence.forEach((phrase, index) => {
				if (phrase.match(/(\.|\?|\!)/g)) {
					feedbackSequence[index - 1] = feedbackSequence[index - 1] + phrase;
					feedbackSequence.splice(index, 1);
				}
			});
			feedbackSequence.forEach((phrase, index) => {
				if (phrase.length === 0 || phrase.trim().length === 0) {
					// remove empty or blank indexes:
					feedbackSequence.splice(index, 1);
				} else if (/^\s/.test(phrase)) {
					// remove empty space at the beginning of phrases:
					phrase = phrase.substring(1);
					feedbackSequence.splice(index, 1, phrase);
				}
			});
			for (const phrase of feedbackSequence) {
				speechSequence.push(new ScenarioPhrase(phrase));
			}
		} else {
			speechSequence.push(new ScenarioPhrase(text));
		}
		return speechSequence;
	}
}

results matching ""

    No results matching ""