File indexing completed on 2024-04-28 15:07:48
0001 /* GCompris - crane.js 0002 * 0003 * SPDX-FileCopyrightText: 2016 Stefan Toncu <stefan.toncu29@gmail.com> 0004 * 0005 * Authors: 0006 * <Marc BRUN> (GTK+ version) 0007 * Stefan Toncu <stefan.toncu29@gmail.com> (Qt Quick port) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 .pragma library 0012 .import QtQuick 2.12 as Quick 0013 .import "qrc:/gcompris/src/core/core.js" as Core 0014 .import GCompris 1.0 as GCompris 0015 0016 var numberLevelsWords = 2 0017 var numberOfLevel 0018 var words3Letters = [] 0019 var words4Letters = [] 0020 var words5Letters = [] 0021 var items 0022 var url = "qrc:/gcompris/src/activities/crane/resource/" 0023 var currentLocale 0024 var names = [] 0025 var names2 = [] 0026 var good = [] 0027 var levels 0028 0029 function start(items_) { 0030 items = items_ 0031 levels = items.levels 0032 numberOfLevel = levels.length 0033 items.currentLevel = Core.getInitialLevel(numberOfLevel) 0034 currentLocale = GCompris.ApplicationInfo.getVoicesLocale(GCompris.ApplicationSettings.locale) 0035 0036 /*: Translators: NOTE: Word list for crane activity. 0037 Translate this into a list of 15–25 simple 3-letter 0038 words separated by semi-colons. The words can only contain 0039 lowercase ASCII letters (a–z). Example: cat;dog;win;red;yes 0040 */ 0041 words3Letters = qsTr("cat;dog;win;red;yes;big;box;air;arm;car;bus;fun;day;eat;hat;leg;ice;old;egg").split(';') 0042 0043 /*: Translators: NOTE: Word list for crane activity. 0044 Translate this into a list of 10–20 simple 4-letter 0045 words separated by semi-colons. The words can only contain 0046 lowercase ASCII letters (a–z). Example: blue;best;good;area 0047 */ 0048 words4Letters = qsTr("blue;best;good;area;bell;coat;easy;farm;food;else;girl;give;hero;help;hour;sand;song").split(';') 0049 0050 /*: Translators: NOTE: Word list for crane activity. 0051 Translate this into a list of 10–20 simple 5-letter 0052 words separated by semi-colons. The words can only contain 0053 lowercase ASCII letters (a–z). Example: happy;child;white;apple 0054 */ 0055 words5Letters = qsTr("happy;child;white;apple;brown;truth;fresh;green;horse;hotel;house;paper;shape;shirt;study").split(';') 0056 0057 Core.shuffle(words3Letters) 0058 Core.shuffle(words4Letters) 0059 Core.shuffle(words5Letters) 0060 initLevel() 0061 } 0062 0063 function stop() { 0064 } 0065 0066 function initLevel() { 0067 items.score.numberOfSubLevels = levels[items.currentLevel].length 0068 items.score.currentSubLevel = 0 0069 initSubLevel() 0070 } 0071 0072 function initSubLevel() { 0073 // reset the arrays 0074 names = [] 0075 names2 = [] 0076 0077 // set models for repeaters 0078 if (!levels[items.currentLevel][items.score.currentSubLevel].isWord) 0079 setModelImage() 0080 else 0081 setModelWord() 0082 0083 // set "initialIndex" to the position in the repeater 0084 for(var i = 0; i < names.length; i++) { 0085 if (items.answerRepeater.itemAt(i).source != "") { 0086 items.answerRepeater.itemAt(i).initialIndex = i 0087 good[i] = i 0088 } 0089 else { 0090 // set the initialIndex to -1 if there is no item inside (no source) 0091 items.answerRepeater.itemAt(i).initialIndex = -1 0092 good[i] = -1 0093 } 0094 } 0095 0096 // select the first item in the grid 0097 for(i = 0; i < items.answerRepeater.count; i++) { 0098 if (items.answerRepeater.itemAt(i).source != "") { 0099 items.selected = i 0100 items.selector.state = "initialized" 0101 break 0102 } 0103 } 0104 items.buttonsBlocked = false; 0105 } 0106 0107 function getInternalWord() { 0108 // function to get a word from translated lists 0109 var currentWordLength = levels[items.currentLevel][items.score.currentSubLevel].wordLength 0110 var wordsUsed 0111 if (currentWordLength === 3) { 0112 wordsUsed = words3Letters 0113 } 0114 else if (currentWordLength === 4) { 0115 wordsUsed = words4Letters 0116 } 0117 else if (currentWordLength === 5) { 0118 wordsUsed = words5Letters 0119 } 0120 // choosing first word of a list and pushing it to the end of the list like a queue. 0121 var word = wordsUsed[0] 0122 wordsUsed.shift() 0123 wordsUsed.push(word) 0124 return word 0125 } 0126 0127 // levels with words as items 0128 function setModelWord() { 0129 var numbers = [] 0130 var i 0131 var wordsUsed 0132 var word = levels[items.currentLevel][items.score.currentSubLevel].word 0133 0134 // show or hide the grid 0135 items.showGrid1.opacity = levels[items.currentLevel][items.score.currentSubLevel].showGrid 0136 // set the two boards in line or not 0137 items.background.inLine = levels[items.currentLevel][items.score.currentSubLevel].inLine 0138 0139 // set the number of columns and rows, be sure we have enough space to display the word 0140 items.columns = levels[items.currentLevel][items.score.currentSubLevel].columns 0141 items.rows = levels[items.currentLevel][items.score.currentSubLevel].rows; 0142 0143 for (i = 0; i < items.columns * items.rows; i++) { 0144 names[i] = "" 0145 names2[i] = "" 0146 numbers[i] = i; // generate columns*rows numbers 0147 } 0148 0149 if(word === undefined) { 0150 word = getInternalWord() 0151 } 0152 0153 // place the word at a random position in the grid 0154 var randomRow = Math.floor(Math.random() * items.rows) 0155 var randomCol = Math.floor(Math.random() * items.columns) 0156 0157 // check if the word goes out of the frame and replace to left it if needed 0158 if (items.columns - randomCol - word.length < 0) 0159 randomCol = randomCol - Math.abs(items.columns - randomCol - word.length) 0160 0161 // set full path (url) to the letter image 0162 var index = 0; 0163 for (i = 0; i < word.length; i++) { 0164 index = randomRow * items.columns + randomCol + i 0165 names[index] = url + "letters/" + word.charAt(i) + ".svg" 0166 names2[index] = names[index] 0167 } 0168 0169 Core.shuffle(names) 0170 0171 // set model for repeaters 0172 items.answerRepeater.model = names.length 0173 items.modelRepeater.model = names2.length 0174 items.gridRepeater.model = names.length 0175 0176 // set the source of items inside repeaters to names and names2 0177 for (i = 0; i < names.length; i++) { 0178 items.answerRepeater.itemAt(i).source = names[i] 0179 items.modelRepeater.itemAt(i).source = names2[i] 0180 } 0181 } 0182 0183 // levels with images as items 0184 function setModelImage() { 0185 var numbers = [] 0186 var i 0187 var imageList = levels[items.currentLevel][items.score.currentSubLevel].images; 0188 0189 // set the number of columns and rows from "levels" 0190 items.columns = levels[items.currentLevel][items.score.currentSubLevel].columns 0191 items.rows = levels[items.currentLevel][items.score.currentSubLevel].rows 0192 0193 for (i = 0; i < items.columns * items.rows; i++) { 0194 names[i] = "" 0195 names2[i] = "" 0196 numbers[i] = i; // generate columns*rows numbers 0197 } 0198 0199 // randomize the names 0200 Core.shuffle(imageList) 0201 0202 //get "levels[items.currentLevel].noOfItems" random numbers 0203 Core.shuffle(numbers) 0204 0205 for (i = 0; i < imageList.length; i++) 0206 names[numbers[i]] = imageList[i] 0207 0208 Core.shuffle(numbers) 0209 0210 for (i = 0; i < imageList.length; i++) 0211 names2[numbers[i]] = imageList[i] 0212 0213 // set model for repeaters 0214 items.answerRepeater.model = names.length 0215 items.modelRepeater.model = names2.length 0216 items.gridRepeater.model = names.length 0217 0218 // set the source of items inside repeaters to names and names2 0219 for (i = 0; i < names.length; i++) { 0220 items.answerRepeater.itemAt(i).source = names[i] 0221 items.modelRepeater.itemAt(i).source = names2[i] 0222 } 0223 0224 // show or hide the grid 0225 items.showGrid1.opacity = levels[items.currentLevel][items.score.currentSubLevel].showGrid 0226 0227 // set the two boards in line or not 0228 items.background.inLine = levels[items.currentLevel][items.score.currentSubLevel].inLine 0229 } 0230 0231 // returns the next index needed for switching to another item 0232 function getNextIndex() { 0233 // get the initialIndex 0234 var index = items.answerRepeater.itemAt(items.selected).initialIndex 0235 0236 var min = 100 0237 var min2 = 100 0238 var biggerIndex = -1 0239 var smallestIndex = -1 0240 0241 for (var i = 0; i < items.answerRepeater.count; i++) { 0242 var currentItemIndex = items.answerRepeater.itemAt(i).initialIndex 0243 // get the immediat bigger index 0244 if (index < currentItemIndex) { 0245 if (min > currentItemIndex) { 0246 // update min and index 0247 min = currentItemIndex 0248 biggerIndex = i 0249 } 0250 } 0251 // in case current index is the biggest, search the smallest index from start 0252 if (currentItemIndex >= 0 && min2 > currentItemIndex) { 0253 min2 = currentItemIndex 0254 smallestIndex = i 0255 } 0256 } 0257 0258 // if a bigger index was found, return it 0259 if (biggerIndex != -1) 0260 return biggerIndex 0261 0262 // this is the biggest index; the next one is the smallest in the array 0263 return smallestIndex 0264 } 0265 0266 //touchscreen gestures 0267 function gesture(deltax, deltay) { 0268 if (Math.abs(deltax) > 40 || Math.abs(deltay) > 40) 0269 if (deltax > 30 && Math.abs(deltay) < items.sensivity) 0270 move("right") 0271 else if (deltax < -30 && Math.abs(deltay) < items.sensivity) 0272 move("left") 0273 else if (Math.abs(deltax) < items.sensivity && deltay > 30) 0274 move("down") 0275 else if (Math.abs(deltax) < items.sensivity && deltay < 30) 0276 move("up") 0277 } 0278 0279 //depending on the command, make a move to left/right/up/down or select next item 0280 function move(command) { 0281 if (items.ok && !items.pieceIsMoving) { 0282 var item = items.answerRepeater.itemAt(items.selected) 0283 if (command === "left") { 0284 if (items.selected % items.columns != 0) 0285 makeMove(item, -item.width, item.x, -1, "x") 0286 } else if (command === "right") { 0287 if ((items.selected+1) % items.columns != 0) 0288 makeMove(item, item.width, item.x, 1, "x") 0289 } else if (command === "up") { 0290 if (items.selected > items.columns-1) 0291 makeMove(item, -item.height, item.y, -items.columns, "y") 0292 } else if (command === "down") { 0293 if (items.selected < (items.answerRepeater.count-items.columns)) 0294 makeMove(item, item.height, item.y, items.columns, "y") 0295 } else if (command === "next") { 0296 items.selected = getNextIndex() 0297 } 0298 } 0299 } 0300 0301 //set the environment for making a move and start the animation 0302 function makeMove(item, distance, startPoint, add, animationProperty) { 0303 if (items.answerRepeater.itemAt(items.selected+add).source == "") { 0304 items.pieceIsMoving = true 0305 //setup the animation 0306 item.distance = distance 0307 item.indexChange = add 0308 item.startPoint = startPoint 0309 item.animationProperty = animationProperty 0310 0311 //start the animation 0312 item.anim.start() 0313 0314 //update the selected item 0315 items.selected += add; 0316 } 0317 } 0318 0319 //check the answer; advance to next level if the answer is good 0320 function checkAnswer() { 0321 var hasWon = true 0322 for (var i = 0; i < items.answerRepeater.count && hasWon; i++) { 0323 if (items.answerRepeater.itemAt(i).source != items.modelRepeater.itemAt(i).source) { 0324 hasWon = false 0325 return; 0326 } 0327 } 0328 items.buttonsBlocked = true; 0329 items.score.currentSubLevel++; 0330 items.score.playWinAnimation(); 0331 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/completetask.wav"); 0332 } 0333 0334 function nextLevel() { 0335 items.score.stopWinAnimation(); 0336 items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel); 0337 initLevel(); 0338 } 0339 0340 function previousLevel() { 0341 items.score.stopWinAnimation(); 0342 items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel); 0343 initLevel(); 0344 } 0345 0346 function nextSubLevel() { 0347 if(items.score.currentSubLevel >= items.score.numberOfSubLevels) { 0348 items.bonus.good("flower") 0349 } else { 0350 initSubLevel(); 0351 } 0352 }