import {FlashMessenger, Helper, Menu, MenuAction, SystemSettings} from "../../../../../js/lib/pwa-lib"; import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer"; import {LevelHelper} from "../wordrotator/Level/LevelHelper"; import {WordRotatorDb} from "../WordRotatorDb"; import {Matomo, ScaleHelper, SoundManager} from "../../../../../js/lib/pwa-assets"; import {EndSite} from "./EndSite"; import {WordRotatorBaseSite} from "./WordRotatorBaseSite"; import {SettingsManager} from "../../../../../js/lib/pwa-core"; import {SimpleFourWordsLevel} from "../wordrotator/Level/SimpleFourWordsLevel"; export class LevelSite extends WordRotatorBaseSite { constructor(siteManager) { super(siteManager, "html/application/level.html"); } createActionBarMenu(menu) { menu = super.createActionBarMenu(menu); let coinAction = new MenuAction(Helper.nonNull(localStorage.getItem("coins"), "0"), () => { }, MenuAction.SHOW_ALWAYS, 900); coinAction.setShouldTranslate(false); coinAction._liClass = "coin-counter"; menu.addAction(coinAction); this.coinAction = coinAction; return menu; } onConstruct(args) { this.levelCounter = Helper.nonNull(localStorage.getItem("levelCounter"), 1); this.levelScaler = () => { }; this.wonParams = { aborted: false, coinCounterTimer: null, }; this.coinPromise = Promise.resolve(); let settingsManager = SettingsManager.getInstance(); let soundManager = SoundManager.getInstance(); soundManager.set({ audio: "sound/single_coin_fall_on_concrete_.mp3", muted: (settingsManager.getSetting("play-sound", "1") !== "1"), volume: 0.7 }, SoundManager.CHANNELS.SOUND); soundManager.resume(SoundManager.CHANNELS.MUSIC); return super.onConstruct(args); } async onFirstStart() { super.onFirstStart(); let leafSegmentTemplate = this.findBy("#segment-leaf-template"); let parentSegmentTemplate = this.findBy("#segment-parent-template"); let rowSegmentTemplate = this.findBy("#segment-row-template"); let triangleTemplate = this.findBy("#segment-triangle-template"); let columnTemplate = this.findBy("#segment-column-template"); leafSegmentTemplate.removeAttribute("id"); parentSegmentTemplate.removeAttribute("id"); rowSegmentTemplate.removeAttribute("id"); triangleTemplate.removeAttribute("id"); columnTemplate.removeAttribute("id"); leafSegmentTemplate.remove(); parentSegmentTemplate.remove(); rowSegmentTemplate.remove(); triangleTemplate.remove(); columnTemplate.remove(); let self = this; let continueButton = this.findBy("#continue-button"); continueButton.addEventListener("click", () => { self.nextLevel(); }); let wonText = this.findBy("#won-text"); let scaleHelper = new ScaleHelper(); this.continueButtonScaler = await scaleHelper.scaleToFull(continueButton, continueButton.parentElement, false, true, 2); this.wonTextScaler = await scaleHelper.scaleToFull(wonText, wonText.parentElement, false, false, 2, null, 5); this.wonText = wonText; this.wonText.style.fontSize = "0"; //Benutze Document, da Element außerhalb von Seite (eigentlich unschön!) this.levelCounterActionContainer = document.getElementById("level-number-container"); this.levelCounterAction = document.getElementById("level-number"); this.levelCounterAction.innerText = this.levelCounter; this.levelNumberScaler = await scaleHelper.scaleToFull(this.levelCounterAction, this.levelCounterActionContainer, false, false, 4); this.levelCounterActionContainer.classList.add("visible"); this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate, columnTemplate); this.coinTemplate = this.findBy("#coin-template"); this.coinContainer = this.findBy("#coin-container"); this.coinTemplate.id = null; this.coinContainer.removeAllChildren(); this.findBy("#help-button").addEventListener("click", () => { this.help(); }); await this.loadLastLevel(); } async loadLastLevel() { try { let currentLevelInfo = localStorage.getItem("currentLevel"); if (Helper.isNotNull(currentLevelInfo)) { currentLevelInfo = JSON.parse(currentLevelInfo); const db = await WordRotatorDb.getInstance(); const levelJson = await db.loadLevel(currentLevelInfo["id"]); if (levelJson === null) { return this.nextLevel(); } let level = LevelHelper.inflateLevel(levelJson, this.templateContainer); level.setStartRotations(currentLevelInfo["rotations"]); const self = this; level.getWonPromise().then(() => { self.levelWon(level); }); level.createSegments(); level.setLocks(currentLevelInfo["locks"]); level.getRootSegment()._updateElement(); level.saveAsCurrentLevel(); let levelSegment = this.findBy("#level"); levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement()); let scaleHelper = new ScaleHelper(); this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0); this.level = level; let res = this.tutorial(); Matomo.push(["trackEvent", "LevelSite", "LoadLastLevel"]); this.level.checkHasWon(); return res; } } catch (e) { console.error(e); } return this.nextLevel(); } startEndSite(){ this.startSite(EndSite); this.finish(); } async nextLevel() { try { this._siteContent.classList.remove('won'); this.wonText.style.fontSize = "0"; const db = await WordRotatorDb.getInstance(); const nextLevelJson = await db.loadNextLevel(LevelSite.RENDERER_TYPES); console.log("nextLevelJson", nextLevelJson); if (nextLevelJson === null) { this.startEndSite(); return; } const level = LevelHelper.inflateLevel(nextLevelJson, this.templateContainer); const self = this; level.getWonPromise().then(() => { self.levelWon(level); }); level.createSegments(); level.getRootSegment()._updateElement(); level.saveAsCurrentLevel(); let levelSegment = this.findBy("#level"); levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement()); let scaleHelper = new ScaleHelper(); this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0); this.level = level; this.levelCounterAction.innerText = this.levelCounter; this.levelNumberScaler(); this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0")); this.coinAction.redraw(); this.wonParams.aborted = true; clearTimeout(this.wonParams.coinCounterTimer); Matomo.push(["trackEvent", "LevelSite", "NextLevel", "Level Number Normal", this.levelCounter]); this.level.checkHasWon(); return this.tutorial(); } catch (e) { console.log("Fehler!"); console.error(e); this.startEndSite(); } } onStart(args) { Matomo.update("Level Site"); let res = super.onStart(args); if (this.levelCounterAction) { this.levelCounterAction.innerText = this.levelCounter; this.levelCounterActionContainer.classList.add("visible"); } this.levelScaler(); let settingsManager = SettingsManager.getInstance(); let soundManager = SoundManager.getInstance(); soundManager.set({ audio: "sound/single_coin_fall_on_concrete_.mp3", muted: (settingsManager.getSetting("play-sound", "1") !== "1"), volume: 0.7 }, SoundManager.CHANNELS.SOUND); return res; } onPause(args) { super.onPause(args); this.levelCounterActionContainer.classList.remove("visible"); } async levelWon(level) { try { const db = await WordRotatorDb.getInstance(); const savePromise = db.saveLevelPlayed(level.getId()); this.levelCounter++; localStorage.setItem("levelCounter", this.levelCounter); this._siteContent.classList.add('won'); localStorage.removeItem("currentLevel"); let continueButton = this.findBy("#continue-button"); continueButton.style.transition = "none"; continueButton.style.opacity = 0; this.coinContainer.removeAllChildren(); let coinsPerLevel = SystemSettings.get("coinsPerLevel", 5); let coinsBefore = 0; let soundManager = SoundManager.getInstance(); let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND); this.coinPromise = this.coinPromise.then(() => { coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")); localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel)); }).then(() => { return Promise.all([new Promise((r) => { setTimeout(() => { r(continueButton.fadeIn()); }, 500) }), audioOptions.loadedPromise.catch(e => { console.error(e) })]); }); this.wonParams.aborted = false; for (let i = 0; i < coinsPerLevel; i++) { let coinElem = Helper.cloneNode(this.coinTemplate); this.coinContainer.appendChild(coinElem); this.coinPromise = this.coinPromise.then(() => { return new Promise(r => { let timeout = 350; if (!this.wonParams.aborted) { coinElem.fadeIn(timeout / 1000); soundManager.play(SoundManager.CHANNELS.SOUND); this.wonParams.coinCounterTimer = setTimeout(() => { if (!this.wonParams.aborted) { this.coinAction.setTitle(++coinsBefore); this.coinAction.redraw(); } }, timeout / 2); } else { r(); } //Always do the next promise for garbage collection setTimeout(r, timeout); }) }); } this.coinPromise = this.coinPromise.catch((e) => { console.error(e) }); this.wonTextScaler(); this.continueButtonScaler(); this.levelScaler(); Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]); await savePromise; } catch (e) { console.error(e); } } help() { let cost = SystemSettings.get("costForHelp", 25); let currentCoins = parseInt(Helper.nonNull(localStorage.getItem("coins"), 0)); if (currentCoins >= cost) { currentCoins -= cost; localStorage.setItem("coins", currentCoins); this.coinAction.title = currentCoins; this.coinAction.redraw(); let rotatables = this.level.getRotatableSegments(); rotatables = rotatables.filter((segment) => { return (!segment.isSolved(false)); }); let index = Math.floor(Math.random() * rotatables.length); let segmentToHelp = rotatables[index]; while (segmentToHelp.rotation !== 0) { segmentToHelp.rotate(); } segmentToHelp.setIsRotatable(false); this.level.saveAsCurrentLevel(); Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]); } else { FlashMessenger.addMessage("not-enough-coins"); Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]); } } async tutorial() { if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) { let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "1"); let scaleHelper = new ScaleHelper(); this._siteContent.classList.add("tutorial"); this._siteContent.classList.add("step-" + currentStep); switch (currentStep) { case "1": { this.level.setSegmentClickedListener(() => { this._siteContent.classList.remove("step-1"); localStorage.setItem("tutorial-step", "2"); this.tutorial(); }); let textElem = this.findBy(".tutorial-text .step-1"); await this.levelScaler(); scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); break; } case "2": { this.level.setSegmentClickedListener(() => { }); this.level.getWonPromise().then(() => { this._siteContent.classList.remove("tutorial"); this._siteContent.classList.remove("step-2"); localStorage.removeItem("tutorial-step"); this.coinPromise = this.coinPromise.then(() => { FlashMessenger.addMessage("extra-coins-after-first-level"); localStorage.setItem("coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")) + 50); this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0")); this.coinAction.redraw(); }); // this.levelScaler(); }); let textElem = this.findBy(".tutorial-text .step-2"); await this.levelScaler(); scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); break; } default:{ this._siteContent.classList.remove("tutorial"); } } } else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) { let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "3"); switch (currentStep) { case "3": { let scaleHelper = new ScaleHelper(); this._siteContent.classList.add("tutorial"); this._siteContent.classList.add("step-" + currentStep); let eventListener = () => { this._siteContent.classList.remove("tutorial"); this._siteContent.classList.remove("step-3"); localStorage.setItem("tutorial-step", "4"); this.findBy("#help-button").removeEventListener("click", eventListener); this.levelScaler(); }; this.findBy("#help-button").addEventListener("click", eventListener); let textElem = this.findBy(".tutorial-text .step-3"); await this.levelScaler(); scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); break; } default:{ this._siteContent.classList.remove("tutorial"); } } } else if (this.level.id === LevelSite.TUTORIAL.BIG_SEGMENT_LEVEL) { let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "4"); switch (currentStep) { case "4": { let scaleHelper = new ScaleHelper(); this._siteContent.classList.add("tutorial"); this._siteContent.classList.add("step-" + currentStep); let rotatableSegments = this.level.getRotatableSegments(); let firstSegment = rotatableSegments[2]; console.log(firstSegment); let pointer = this.findBy("#tutorial-pointer"); pointer.remove(); firstSegment.element.appendChild(pointer); this.level.setSegmentClickedListener((segment) => { console.log("clicked Segment", segment); if (firstSegment === segment) { this._siteContent.classList.remove("tutorial"); this._siteContent.classList.remove("step-4"); localStorage.setItem("tutorial-step", "5"); this.levelScaler(); } }); let textElem = this.findBy(".tutorial-text .step-4"); await this.levelScaler(); scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); break; } default:{ this._siteContent.classList.remove("tutorial"); } } } } } LevelSite.RENDERER_TYPES = [20, 40, 60, 80, 81, 82, 83, 100, 120, 140, 160]; LevelSite.TUTORIAL = { FIRST_LEVEL: 67, SECOND_LEVEL: 15, BIG_SEGMENT_LEVEL: 1921 };