File indexing completed on 2024-05-05 15:53:02
0001 /* GCompris - click_on_letter.js 0002 * 0003 * SPDX-FileCopyrightText: 2014 Holger Kaelberer 0004 * 0005 * Authors: 0006 * Pascal Georges <pascal.georges1@free.fr> (GTK+ version) 0007 * Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ Mostly full rewrite) 0008 * Holger Kaelberer <holger.k@elberer.de> (Qt Quick port) 0009 * 0010 * SPDX-License-Identifier: GPL-3.0-or-later 0011 */ 0012 0013 .pragma library 0014 .import QtQuick 2.12 as Quick 0015 .import GCompris 1.0 as GCompris //for ApplicationInfo 0016 .import "qrc:/gcompris/src/core/core.js" as Core 0017 0018 var url = "qrc:/gcompris/src/activities/click_on_letter/resource/" 0019 var defaultLevelsFile = ":/gcompris/src/activities/click_on_letter/resource/levels-en.json"; 0020 var maxLettersPerLine = 6; 0021 0022 var levels; 0023 var numberOfLevel; 0024 var currentLetter; 0025 var level; 0026 var questions; 0027 var answers; 0028 var items; 0029 var mode; 0030 0031 function start(_items, _mode) 0032 { 0033 Core.checkForVoices(_items.activityPage); 0034 0035 items = _items; 0036 mode = _mode; 0037 0038 // register the voices for the locale 0039 var locale = GCompris.ApplicationInfo.getVoicesLocale(items.locale) 0040 GCompris.DownloadManager.updateResource(GCompris.GCompris.VOICES, {"locale": locale}) 0041 0042 loadLevels(); 0043 items.score.currentSubLevel = 0; 0044 numberOfLevel = levels.length; 0045 items.currentLevel = Core.getInitialLevel(numberOfLevel); 0046 initLevel(); 0047 } 0048 0049 function validateLevels(levels) 0050 { 0051 var i; 0052 for (i = 0; i < levels.length; i++) { 0053 if (undefined === levels[i].questions 0054 || typeof levels[i].questions != "string" 0055 || levels[i].questions.length < 1 0056 || typeof levels[i].answers != "string" 0057 || levels[i].answers.length < 1) 0058 return false; 0059 } 0060 if (i < 1) 0061 return false; 0062 return true; 0063 } 0064 0065 function loadLevels() 0066 { 0067 var ret; 0068 var locale = GCompris.ApplicationInfo.getVoicesLocale(items.locale) 0069 var filename = GCompris.ApplicationInfo.getLocaleFilePath(url + "levels-" + locale + ".json"); 0070 levels = items.parser.parseFromUrl(filename); 0071 if (levels == null) { 0072 console.warn("Click_on_letter: Invalid levels file " + filename); 0073 // fallback to default Latin (levels-en.json) file: 0074 levels = items.parser.parseFromUrl(defaultLevelsFile); 0075 if (levels == null) { 0076 console.error("Click_on_letter: Invalid default levels file " 0077 + defaultLevelsFile + ". Can't continue!"); 0078 // any way to error-exit here? 0079 return; 0080 } 0081 } 0082 // at this point we have valid levels 0083 for (var i = 0; i < levels.length; i++) { 0084 if (mode === "lowercase") { 0085 levels[i].questions = levels[i].questions.toLocaleLowerCase(); 0086 levels[i].answers = levels[i].answers.toLocaleLowerCase(); 0087 } else { 0088 levels[i].questions = levels[i].questions.toLocaleUpperCase(); 0089 levels[i].answers = levels[i].answers.toLocaleUpperCase(); 0090 } 0091 } 0092 } 0093 0094 function stop() 0095 { 0096 } 0097 0098 function shuffleString(s) 0099 { 0100 var a = s.split("|"); 0101 var n = a.length; 0102 0103 for(var i = n-1; i>0; i--) { 0104 var j = Math.floor(Math.random() * (i + 1)); 0105 var tmp = a[i]; 0106 a[i] = a[j]; 0107 a[j] = tmp; 0108 } 0109 return a.join("|"); 0110 } 0111 0112 function initLevel() { 0113 items.errorRectangle.resetState(); 0114 if (items.score.currentSubLevel == 0) { 0115 level = levels[items.currentLevel]; 0116 items.score.numberOfSubLevels = level.questions.split("|").length; 0117 questions = shuffleString(level.questions); 0118 answers = shuffleString(level.answers); 0119 0120 var answerArr = answers.split("|"); 0121 items.trainModel.clear(); 0122 for (var i = 0; i < answerArr.length; i++) { 0123 items.trainModel.append({ 0124 "letter": answerArr[i], 0125 }); 0126 } 0127 } 0128 0129 var locale = GCompris.ApplicationInfo.getVoicesLocale(items.locale); 0130 currentLetter = questions.split("|")[items.score.currentSubLevel]; 0131 if (GCompris.ApplicationSettings.isAudioVoicesEnabled && 0132 GCompris.DownloadManager.haveLocalResource( 0133 GCompris.DownloadManager.getVoicesResourceForLocale(locale))) { 0134 items.audioVoices.append(GCompris.ApplicationInfo.getAudioFilePath("voices-$CA/"+locale+"/misc/click_on_letter.$CA")) 0135 items.audioVoices.silence(100) 0136 playLetter(currentLetter) 0137 items.questionItem.visible = false 0138 items.repeatItem.visible = true 0139 } else { 0140 // no sound -> show question 0141 items.questionItem.visible = true; 0142 items.repeatItem.visible = false 0143 } 0144 // Maybe we will display it if sound fails 0145 items.questionItem.text = currentLetter; 0146 0147 items.buttonsBlocked = false; 0148 } 0149 0150 function playLetter(letter) { 0151 var locale = GCompris.ApplicationInfo.getVoicesLocale(items.locale) 0152 items.audioVoices.append(GCompris.ApplicationInfo.getAudioFilePath("voices-$CA/"+locale+"/alphabet/" 0153 + Core.getSoundFilenamForChar(letter))) 0154 } 0155 0156 function nextLevel() { 0157 items.score.stopWinAnimation(); 0158 items.audioVoices.clearQueue(); 0159 items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel); 0160 items.score.currentSubLevel = 0; 0161 initLevel(); 0162 } 0163 0164 function previousLevel() { 0165 items.score.stopWinAnimation(); 0166 items.audioVoices.clearQueue(); 0167 items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel); 0168 items.score.currentSubLevel = 0; 0169 initLevel(); 0170 } 0171 0172 function nextSubLevel() { 0173 items.audioVoices.clearQueue() 0174 if(items.score.currentSubLevel >= items.score.numberOfSubLevels) { 0175 items.bonus.good("flower") 0176 } else { 0177 initLevel(); 0178 } 0179 } 0180 0181 function checkAnswer(index) { 0182 var modelEntry = items.trainModel.get(index); 0183 if (modelEntry.letter === currentLetter) { 0184 items.score.currentSubLevel++; 0185 items.score.playWinAnimation(); 0186 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/completetask.wav"); 0187 return true 0188 } else { 0189 return false 0190 } 0191 } 0192 0193 function focusEventHandler() { 0194 if (items && items.eventHandler) 0195 items.eventHandler.forceActiveFocus(); 0196 }