diff --git a/src/activities/alphabetical_order/AlphabeticalOrder.qml b/src/activities/alphabetical_order/AlphabeticalOrder.qml index 3c09ac86c..0b7ecb617 100644 --- a/src/activities/alphabetical_order/AlphabeticalOrder.qml +++ b/src/activities/alphabetical_order/AlphabeticalOrder.qml @@ -1,724 +1,742 @@ /* GCompris - alphabetical_order.qml * * Copyright (C) 2016 Stefan Toncu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.1 import GCompris 1.0 import "../../core" import "alphabetical_order.js" as Activity ActivityBase { id: activity onStart: focus = true onStop: {} pageComponent: Rectangle { id: background anchors.fill: parent color: "#fffae6" signal start signal stop // system locale by default property string locale: "system" Component.onCompleted: { activity.start.connect(start) activity.stop.connect(stop) dialogActivityConfig.getInitialConfiguration() } // Add here the QML items you need to access in javascript QtObject { id: items property Item main: activity.main property GCAudio audioVoices: activity.audioVoices property alias background: background property alias bar: bar property alias bonus: bonus property alias score: score property alias listModel: listModel property alias listModelInput: listModelInput property alias repeater: repeater property alias inputRepeater: inputRepeater property alias locale: background.locale property alias wordlist: wordlist + property alias message: message property bool gameFinished: false property int delay: 6 property bool okBoxChecked: false property bool easyMode: true property bool playLetter: true property double startTime } onStart: { Activity.start(items) } onStop: { Activity.stop() } onFocusChanged: { if(focus) { Activity.focusTextInput() } } + IntroMessage { + id: message + z: 1 + anchors { + top: parent.top + topMargin: 10 + right: parent.right + rightMargin: 5 + left: parent.left + leftMargin: 5 + } + intro: [ + qsTr("Drag and alphabetically order the letters from bottom to their place on top.") + ] + Behavior on opacity { PropertyAnimation { duration: 200 } } + } + ListModel { id: listModel } ListModel { id: listModelInput } property int delay: 20 function resetTime(timeDelay) { items.startTime = Math.round(Activity.date.getTime() / 1000) background.delay = timeDelay } // checks if the user had not made a move in "background.delay" time and shows help Timer { interval: 2000; running: true; repeat: true onTriggered: { // reinitialize the date Activity.date = new Date() // check if "background.delay" time has passed since the last move if (Math.round(Activity.date.getTime() / 1000) - items.startTime > background.delay ) { // on easyMode, show the first "good" move if (items.easyMode) { for (var i = 0; i < items.listModel.count; i++) { var found = false // letter at index i is in the wrong place if (items.listModel.get(i).letter != Activity.solution[i]) { // search for the good letter in the listModel for (var j = 0; j < items.listModel.count; j++) { if (items.listModel.get(j).letter == Activity.solution[i]) { items.repeater.itemAt(i).failureAnimation.start() items.repeater.itemAt(j).failureAnimation.start() found = true break } } // search for the good letter in the listModelInput if (!found) { for (j = 0; j < items.listModelInput.count; j++) if (items.listModelInput.get(j).letter == Activity.solution[i]) { items.repeater.itemAt(i).failureAnimation.start() items.inputRepeater.itemAt(j).failureAnimation1.start() break } } // found the first wrong => break break } } // if not easy mode, show all the wrong placed letters } else { for (i = 0; i < items.listModel.count; i++) // letter at index i is in the wrong place if (items.listModel.get(i).letter != Activity.solution[i]) items.repeater.itemAt(i).failureAnimation.start() } // repeat after 10 seconds background.resetTime(10) } } } Timer { id: finishAnimation interval: 100 repeat: true // repeater index of item to load the particles property int index: 0 // how much the game should wait untill passing to next level property int delay: items.delay onTriggered: { if (index < items.repeater.count) { // start the particles at index, then increment index items.repeater.itemAt(index).particleLoader.item.burst(40) index++ } else if (index < items.repeater.count + delay) { // wait for the dealy time to pass index++ } else { // pass the level stop() bonus.good("tux") } } } Image { id: board source: "resource/blackboard.svg" sourceSize.height: parent.height * 0.8 sourceSize.width: parent.width * 0.8 width: parent.width * 0.8 height: parent.height * 0.8 anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter verticalCenterOffset: -50 } Rectangle { id: topRectangle width: Activity.computeWidth(items.repeater) + solutionArea.spacing * (items.repeater.count - 0.5) height: board.height / 2 color: "transparent" anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter verticalCenterOffset: - height / 2 } Flow { id: solutionArea spacing: (board.width- Activity.computeWidth(items.repeater)) / listModel.count anchors.centerIn: parent Repeater { id: repeater anchors.horizontalCenter: parent.horizontalCenter model: listModel GCText { id: letter text: listModel.get(index) ? listModel.get(index).letter : "" fontSize: hugeSize color: "white" // store the initial coordinates property var _x property var _y property alias particleLoader: particleLoader property alias failureAnimation: failureAnimation // Create a particle only for the strawberry Loader { id: particleLoader anchors.fill: parent active: true sourceComponent: particle } Component { id: particle ParticleSystemStarLoader { id: particles clip: false } } SequentialAnimation { id: failureAnimation PropertyAction { target: letter; property: "color"; value: "red" } NumberAnimation { target: letter; property: "scale"; to: 2; duration: 400 } NumberAnimation { target: letter; property: "scale"; to: 1; duration: 400 } NumberAnimation { target: letter; property: "opacity"; to: 0; duration: 100 } PropertyAction { target: letter; property: "color"; value: "white" } NumberAnimation { target: letter; property: "opacity"; to: 1; duration: 400 } } MouseArea { id: mouseArea anchors.fill: parent drag.target: parent enabled: items.gameFinished || letter.text == '_' ? false : true onPressed: { letter._x = letter.x letter._y = letter.y if (items.playLetter) Activity.playLetter(letter.text) background.resetTime(20) } onReleased: { /* use mouse's coordinates (x and y) to compare to the solutionArea's repeater items */ // map the mouse coordinates to background coordinates var mouseMapped = mapToItem(background,mouse.x,mouse.y) //search through the repeater's items to find if THIS item can replace it for (var i=0; i itemMapped.x && mouseMapped.x < itemMapped.x + item.width && mouseMapped.y > itemMapped.y && mouseMapped.y < itemMapped.y + item.height * 2) { // interchange the letters var textAux = items.listModel.get(i).letter items.listModel.setProperty(i,"letter",letter.text) items.listModel.setProperty(index,"letter",textAux) // animations & particles if (index != i) { if (Activity.solution[i] == items.repeater.itemAt(i).text) { // both letters are in the right position if (Activity.solution[index] == letter.text) { // start the particle only if the solution is partially correct if (!Activity.checkCorectness() && items.easyMode) { items.repeater.itemAt(i).particleLoader.item.burst(40) items.repeater.itemAt(index).particleLoader.item.burst(40) } if (items.okBoxChecked && items.easyMode) { items.repeater.itemAt(i).particleLoader.item.burst(40) items.repeater.itemAt(index).particleLoader.item.burst(40) } // only itemAt(i) is in the right position } else { if (items.easyMode) items.repeater.itemAt(i).particleLoader.item.burst(40) if (items.repeater.itemAt(index).text != '_' && items.easyMode) // only start failureAnimation for letters, not '_' items.repeater.itemAt(index).failureAnimation.start() } // only itemAt(index), meaning only the current item is in the right position } else { if (Activity.solution[index] == letter.text && items.easyMode) { letter.particleLoader.item.burst(40) if (items.repeater.itemAt(i).text != '_' && items.easyMode) items.repeater.itemAt(i).failureAnimation.start() } // both letters are in a wrong position else { if (items.repeater.itemAt(i).text != '_' && items.easyMode) items.repeater.itemAt(i).failureAnimation.start() if (items.repeater.itemAt(index).text != '_' && items.easyMode) items.repeater.itemAt(index).failureAnimation.start() } } } } } // search through the inputRepeater's items to find if THIS item can replace it for (i=0; i itemMapped1.x && mouseMapped.x < itemMapped1.x + item1.width && mouseMapped.y > itemMapped1.y && mouseMapped.y < itemMapped1.y + item1.height * 2) { // interchange the letters var textAux1 = items.listModelInput.get(i).letter if (textAux1 != '_' && letter.text != '_') { items.listModelInput.setProperty(i,"letter",letter.text) items.listModel.setProperty(index,"letter",textAux1) // stop searching for another item; only this one can match the mouse's coordinates break } } } // move the letter back to its initial position letter.x = letter._x letter.y = letter._y // if the solution is correct, start the finishAnimation if (!items.okBoxChecked && Activity.checkCorectness()) { items.gameFinished = true finishAnimation.index = 0 finishAnimation.start() } background.resetTime(20) } } } } } } Rectangle { id: bottomRectangle width: Activity.computeWidth(items.inputRepeater) + inputArea.spacing * (items.inputRepeater.count - 0.5) height: parent.height / 2.1 color: "transparent" anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter verticalCenterOffset: height / 2 } Flow { id: inputArea spacing: (board.width - Activity.computeWidth(items.inputRepeater)) / listModelInput.count anchors.centerIn: parent Repeater { id: inputRepeater anchors.horizontalCenter: parent.horizontalCenter model: listModelInput GCText { id: missingLetter text: listModelInput.get(index) ? listModelInput.get(index).letter : "" fontSize: hugeSize color: "white" // store the initial coordinates property var _x property var _y property alias failureAnimation1: failureAnimation1 SequentialAnimation { id: failureAnimation1 PropertyAction { target: missingLetter; property: "color"; value: "red" } NumberAnimation { target: missingLetter; property: "scale"; to: 2; duration: 400 } NumberAnimation { target: missingLetter; property: "scale"; to: 1; duration: 400 } NumberAnimation { target: missingLetter; property: "opacity"; to: 0; duration: 100 } PropertyAction { target: missingLetter; property: "color"; value: "white" } NumberAnimation { target: missingLetter; property: "opacity"; to: 1; duration: 400 } } MouseArea { id: mouseArea2 anchors.fill: parent drag.target: parent enabled: items.gameFinished ? false : true onPressed: { missingLetter._x = missingLetter.x missingLetter._y = missingLetter.y if (items.playLetter) Activity.playLetter(missingLetter.text) background.resetTime(20) } onReleased: { /* use mouse's coordinates (x and y) to compare to the solutionArea's repeater items */ var mouseMapped = mapToItem(background,mouse.x,mouse.y) //search through the repeater's items to find if THIS item should replace it for (var i=0; i itemMapped.x && mouseMapped.x < itemMapped.x + item.width && mouseMapped.y > itemMapped.y && mouseMapped.y < itemMapped.y + item.height) { var textAux = items.listModel.get(i).letter // if the letter at index i in the repeater is '_', then replace '_' with missingLetter.text if (textAux == '_') { items.listModel.setProperty(i,"letter",missingLetter.text) items.listModelInput.setProperty(index,"letter",'_') // set opacity to 0 and disable the MouseArea of missingLetter items.inputRepeater.itemAt(index).opacity = 0 parent.enabled = false // else, the letter at intex i is a normal letter, so interchange it with missingLetter.text } else { items.listModel.setProperty(i,"letter",missingLetter.text) items.listModelInput.setProperty(index,"letter",textAux) } // if the letter is placed in the correct spot, the particle is activated for item at index i if (Activity.solution[i] == items.listModel.get(i).letter) { // start the particle only if the solution is partially correct if (!Activity.checkCorectness() && items.easyMode) items.repeater.itemAt(i).particleLoader.item.burst(40) if (items.okBoxChecked && items.easyMode) items.repeater.itemAt(i).particleLoader.item.burst(40) // else, the letter is placed in a wrong place; start the failureAnimation } else if (items.easyMode) items.repeater.itemAt(i).failureAnimation.start() // stop searching for another item; only this one can match the mouse's coordinates break } } // move the missingLetter back to its initial position missingLetter.x = missingLetter._x missingLetter.y = missingLetter._y // if the solution is correct, start the finishAnimation if (!items.okBoxChecked && Activity.checkCorectness()) { items.gameFinished = true finishAnimation.index = 0 finishAnimation.start() } background.resetTime(20) } } } } } } } BarButton { id: okButton source: "qrc:/gcompris/src/core/resource/bar_ok.svg" sourceSize.width: Math.min(66 * bar.barZoom, background.width / background.height * 100) visible: items.okBoxChecked enabled: items.gameFinished ? false : true anchors { bottom: bar.top left: parent.left } MouseArea { id: mouseAreaOk anchors.fill: parent property bool bad: false onClicked: { print("bad: ",mouseAreaOk.bad) if (Activity.checkCorectness()) { // set the game to "finished" items.gameFinished = true // start the finishAnimation finishAnimation.index = 0 finishAnimation.start() // the level was won -> add 1 to progress if (mouseAreaOk.bad == false) { //current level was not failed before print("add 1") Activity.progress = Activity.progress.concat(1) } mouseAreaOk.bad = false } else { for (var i = 0; i < items.listModel.count; i++) if (Activity.solution[i] !== items.listModel.get(i).letter) { // letters are different => not correct mouseAreaOk.bad = true items.repeater.itemAt(i).failureAnimation.start() // saving current state (model and modelAux) in a vector for using it again var ok = true for (var j = 0; j < Activity.badAnswers.length; j++) // current state already in the vetor if (Activity.badAnswers[j].model == Activity.model && Activity.badAnswers[j].modelAux == Activity.modelAux) ok = false // ok == true only if the current state is not already in the vector if (ok == true) // add current state to the vector Activity.badAnswers = Activity.badAnswers.concat({model: Activity.model, modelAux: Activity.modelAux, solution: Activity.solution}) print("Wrong: _________") for (j = 0; j < Activity.badAnswers.length; j++) print(Activity.badAnswers[j].model + " " + Activity.badAnswers[j].modelAux + " " + Activity.badAnswers[j].solution) } // decrease the levelsPassed counter if (mouseAreaOk.bad && Activity.levelsPassed >= 1) { Activity.levelsPassed -- } // the level was lost -> add 0 to progress Activity.progress = Activity.progress.concat(0) print("add 0") print("progress: ",Activity.progress) } background.resetTime(20) } } } DialogActivityConfig { id: dialogActivityConfig currentActivity: activity content: Component { Item { property alias localeBox: localeBox height: column.height property alias availableLangs: langs.languages LanguageList { id: langs } Column { id: column spacing: 10 width: parent.width Flow { spacing: 5 width: dialogActivityConfig.width GCComboBox { id: localeBox model: langs.languages background: dialogActivityConfig label: qsTr("Select your locale") } } /* TODO handle this: GCDialogCheckBox { id: uppercaseBox width: 250 * ApplicationInfo.ratio text: qsTr("Uppercase only mode") checked: true onCheckedChanged: { print("uppercase changed") } } */ GCDialogCheckBox { id: okButtonBox width: 250 * ApplicationInfo.ratio text: qsTr("OK button active") checked: items.okBoxChecked onCheckedChanged: { items.okBoxChecked = checked okButton.visible = checked print("okButtonBox: ",checked) Activity.currentLevel = 0 Activity.progress = [] score.currentSubLevel = 1 Activity.initLevel() } } GCDialogCheckBox { id: easyModeBox width: 250 * ApplicationInfo.ratio text: qsTr("Easy mode") checked: items.easyMode onCheckedChanged: { print("easyModeBox: ",checked) items.easyMode = checked } } GCDialogCheckBox { id: playLetterBox width: 250 * ApplicationInfo.ratio text: qsTr("Play letter sound") checked: items.playLetter onCheckedChanged: { print("playLetterBox: ",checked) items.playLetter = checked } } } } } onClose: home() onLoadData: { if(dataToSave && dataToSave["locale"]) { background.locale = dataToSave["locale"]; } } onSaveData: { var oldLocale = background.locale; var newLocale = dialogActivityConfig.configItem.availableLangs[dialogActivityConfig.loader.item.localeBox.currentIndex].locale; // Remove .UTF-8 if(newLocale.indexOf('.') != -1) { newLocale = newLocale.substring(0, newLocale.indexOf('.')) } dataToSave = {"locale": newLocale} background.locale = newLocale; // Restart the activity with new information if(oldLocale !== newLocale) { background.stop(); background.start(); } } function setDefaultValues() { var localeUtf8 = background.locale; if(background.locale != "system") { localeUtf8 += ".UTF-8"; } for(var i = 0 ; i < dialogActivityConfig.configItem.availableLangs.length ; i ++) { if(dialogActivityConfig.configItem.availableLangs[i].locale === localeUtf8) { dialogActivityConfig.loader.item.localeBox.currentIndex = i; break; } } } } Wordlist { id: wordlist defaultFilename: Activity.dataSetUrl + "default-en.json" // To switch between locales: xx_XX stored in configuration and // possibly correct xx if available (ie fr_FR for french but dataset is fr.) useDefault: false filename: "" onError: console.log("Reading: Wordlist error: " + msg); } Score { id: score currentSubLevel: 1 numberOfSubLevels: 5 } DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | level | config } onHelpClicked: { displayDialog(dialogHelp) } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() onConfigClicked: { dialogActivityConfig.active = true dialogActivityConfig.setDefaultValues() displayDialog(dialogActivityConfig) } } Bonus { id: bonus Component.onCompleted: win.connect(Activity.nextSubLevel) } } } diff --git a/src/activities/alphabetical_order/alphabetical_order.js b/src/activities/alphabetical_order/alphabetical_order.js index cd1504ba5..d4fea7e89 100644 --- a/src/activities/alphabetical_order/alphabetical_order.js +++ b/src/activities/alphabetical_order/alphabetical_order.js @@ -1,381 +1,385 @@ /* GCompris - alphabetical_order.js * * Copyright (C) 2016 Stefan Toncu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ .pragma library .import QtQuick 2.0 as Quick .import GCompris 1.0 as GCompris //for ApplicationInfo .import "qrc:/gcompris/src/core/core.js" as Core var currentLevel = 0 var numberOfLevel = 10 var items var alphabet = [] var asciiAlphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] var solution = [] var dataSetUrl= "qrc:/gcompris/src/activities/gletters/resource/" var totalLettersNoOk = [3,3,5,5,6,6,6,7,8,8] var guessLettersNoOk = [2,3,2,2,2,2,3,3,4,5] var totalLetters = 3 var guessLetters = 1 var modelAux var model var badAnswers = [] //[{model: [], modelAux: [], solution: []}] var levelsPassed = 0 var difficulty = 0 // 0 = extremely easy; 1 = very easy; 2 = easy; 3 = normal; 4 = hard; 5 = very hard; 6 = insane // 0 = extremely easy: totalLetters = [3]; guessLetters = [1-2] // 1 = very easy: totalLetters = [3]; guessLetters = [2-3] // 2 = easy: totalLetters = [4]; guessLetters = [2-4] // 3 = normal: totalLetters = [5]; guessLetters = [3-4] // 4 = hard: totalLetters = [6]; guessLetters = [3-5] // 5 = very hard: totalLetters = [7]; guessLetters = [4-6] // 6 = insane: totalLetters = [8]; guessLetters = [6-8] var interchange = 1 //var progress = {totalPassed: 0, totalFailed: 0, lastSubLevel: 0} // lastSubLevel = 0 if lost; = 1 if won var progress = [] // 0 if lost, 1 if won => [1,1,0,1,1,0,0,1,1,1,1,1...] var date function start(items_) { items = items_ currentLevel = 0 progress = [] date = new Date() items.startTime = Math.round(date.getTime() / 1000) print("time: ", items.startTime) items.score.numberOfSubLevels = 5 items.score.currentSubLevel = 1 //imported from "readingh" activity var locale = items.locale == "system" ? "$LOCALE" : items.locale items.wordlist.loadFromFile(GCompris.ApplicationInfo.getLocaleFilePath( dataSetUrl + "default-"+locale+".json")); // If wordlist is empty, we try to load from short locale and if not present again, we switch to default one var localeUnderscoreIndex = locale.indexOf('_') // probably exist a better way to see if the list is empty if(items.wordlist.maxLevel == 0) { var localeShort; // We will first look again for locale xx (without _XX if exist) if(localeUnderscoreIndex > 0) { localeShort = locale.substring(0, localeUnderscoreIndex) } else { localeShort = locale; } // If not found, we will use the default file items.wordlist.useDefault = true items.wordlist.loadFromFile(GCompris.ApplicationInfo.getLocaleFilePath( dataSetUrl + "default-"+localeShort+".json")); // We remove the using of default file for next time we enter this function items.wordlist.useDefault = false } //setup the alphabet from file createAlphabet() initLevel() } function stop() { } function initLevel() { items.bar.level = currentLevel + 1 date = new Date() items.startTime = Math.round(date.getTime() / 1000) + if (currentLevel == 0 && items.score.currentSubLevel == 1) { + items.message.opacity = 1 + } else items.message.opacity = 0 + // custom levels - change difficulty starting from level two (so the user gives feedback from solving at least 5 sublevels) if (currentLevel > 0 && items.okBoxChecked) { print("PROGRESS: ",progress) var currentProgress = progress.slice(Math.max(progress.length - 5,0),progress.length) // take only the last 6 levels var sum = currentProgress.reduce(function(a, b) { return a + b; }, 0) if (sum == 5) { // do not increase difficulty if the last 2 sublevels were fails if (progress[progress.length - 1] != 0 && progress[progress.length - 2] != 0) { if (difficulty <= 4) difficulty += 2 else difficulty = 6 print("sum is 5; difficulty increased by 2: ", difficulty) } } else if (sum == 4) { if (progress[progress.length - 1] != 0 && progress[progress.length - 2] != 0) { if (difficulty <= 5) difficulty ++ print("sum is 4; difficulty increased by 1: ", difficulty) } } else if (sum == 2) { if (difficulty >= 1) difficulty -- print("sum is 2; difficulty decreased by 1: ", difficulty) } else if (sum < 2) { if (difficulty >= 2) difficulty -= 2 else difficulty = 0 print("sum is lower than 2; difficulty decreased by 2: ", difficulty) } } init() } function init() { items.gameFinished = false if (!items.okBoxChecked) { totalLetters = totalLettersNoOk[currentLevel] guessLetters = guessLettersNoOk[currentLevel] if (currentLevel < 3) interchange = 0 else interchange = Math.floor(currentLevel / 2) } else { // setup number of total letters and guess letters depending the difficulty if (difficulty == 0) { interchange = 0 totalLetters = 3 //var randMinMax = Math.floor(Math.random() * (max - min + 1)) + min; guessLetters = Math.floor(Math.random() * (2 - 1 + 1) + 1) } else if (difficulty == 1) { interchange = 0 totalLetters = 3 guessLetters = Math.floor(Math.random() * (3 - 2 + 1) + 2) } else if (difficulty == 2) { interchange = 0 totalLetters = 4 guessLetters = Math.floor(Math.random() * (4 - 2 + 1)) + 2 } else if (difficulty == 3) { interchange = 0 totalLetters = 5 guessLetters = Math.floor(Math.random() * (4 - 3 + 1)) + 3 } else if (difficulty == 4) { interchange = 1 totalLetters = 6 guessLetters = Math.floor(Math.random() * (5 - 3 + 1)) + 3 } else if (difficulty == 5) { interchange = 2 totalLetters = 7 guessLetters = Math.floor(Math.random() * (6 - 4 + 1)) + 4 } else if (difficulty == 6) { interchange = 4 totalLetters = 8 guessLetters = Math.floor(Math.random() * (8 - 6 + 1)) + 6 } else { print("difficulty?? ",difficulty) } } // if 2 levels have past and there are badAnsers saved, assign them as model and modelAux if (levelsPassed >= 2 && badAnswers.length != 0) { // set as model and modelAux a previous state wrongly solved by the user if(badAnswers.length > 0) { model = badAnswers[0].model modelAux = badAnswers[0].modelAux solution = badAnswers[0].solution } print("len: ", badAnswers.length - 1) // remove first element in vector badAnsers badAnswers = badAnswers.slice(1,badAnswers.length) print("len: ", badAnswers.length) print("after ___________") for (var j = 0; j < badAnswers.length; j++) { print(badAnswers[j].model + " " + badAnswers[j].modelAux + " " + badAnswers[j].solution) } // else, use normal levels } else { if (badAnswers.length == 0) levelsPassed = 0 // ['a','b','c','d'] if (currentLevel > 1) solution = makeSolution(alphabet, totalLetters) // just for first level, use the standard english (ascii) alphabet else solution = makeSolution(asciiAlphabet, totalLetters) // 3 1 4 2 var numbers = getNumbers(totalLetters) // ['a','_','c','_'] model = solution.slice() // ['b', 'd'] modelAux = [] for (var i = 0; i < guessLetters; i++) { model[numbers[i]] = '_' modelAux[i] = solution[numbers[i]] } // from level 6 to 8 interchange two good letters // repeat the interchange for (var k = 0; k < interchange; k++) { print("interchange") var a = Math.floor(Math.random() * (totalLetters)) var b = Math.floor(Math.random() * (totalLetters)) while (b == a) b = Math.floor(Math.random() * (totalLetters)) var aux = model[a] model[a] = model[b] model[b] = aux } // a level was passed levelsPassed ++ } // setting levels to repeaters (listModels) items.listModel.clear() items.listModelInput.clear() for (i = 0; i < modelAux.length; i++) items.listModelInput.append({"letter": modelAux[i]}) for (i = 0; i < model.length; i++) items.listModel.append({"letter": model[i]}) } /* goes through each level (in gletters json files) and appends all letters (removing digits and uppercase duplicates) in the alphabet */ function createAlphabet() { alphabet = [] // all "words" for (var i = 1; i < items.wordlist.wordList.levels.length; i++) { var words = items.wordlist.getLevelWordList(i).words // all letters in "words" for (var j = 0; j < words.length; j++) { if (alphabet.indexOf(words[j].toLowerCase()) < 0 && (words[j] >= '0' && words[j] <= '9') == false ) { alphabet = alphabet.concat(words[j]) } } } // sort the alphabet alphabet = GCompris.ApplicationInfo.localeSort(alphabet) } function sortNumber(a,b) { return a - b; } // generate a randomized array with "len" numbers function getNumbers(len) { var numbers = [] for (var i = 0; i < len; i++) { numbers[i] = i } numbers = Core.shuffle(numbers) return numbers } // generate an array with "noOfLetters" letters taken from "alphabet" function makeSolution(alphabet, noOfLetters) { var solution = [] var aux = getNumbers(alphabet.length) //"noOfLetters" numbers sorted of "alphabet.length" numbers shuffeled var generate = [] for (var i = 0; i < noOfLetters; i++) { generate[i] = aux[i] } generate.sort(sortNumber) for (i = 0; i < noOfLetters; i++) { solution[i] = alphabet[generate[i]] } return solution } // check if the user's answer matches the solution function checkCorectness() { var nr = solution.length //if the two do not have the same length -> false if (nr !== items.listModel.count) return false for (var i = 0; i < nr; i++) if (solution[i] !== items.listModel.get(i).letter) { return false // the letters are different at index i -> false } return true } // compute maximum width of the letters in the repeater given as parameter function computeWidth(repeater) { if (repeater == null) return 0 var max = -1 for (var i = 0; i < repeater.count; i++) { if (max < repeater.itemAt(i).width) max = repeater.itemAt(i).width } return max * repeater.count } function nextLevel() { items.score.currentSubLevel = 1 if(numberOfLevel <= ++currentLevel ) { currentLevel = 0 } initLevel(); } function nextSubLevel() { if (items.score.numberOfSubLevels >= ++items.score.currentSubLevel) { initLevel() } else { nextLevel() } } function previousLevel() { items.score.currentSubLevel = 1 if(--currentLevel < 0) { currentLevel = numberOfLevel - 1 } initLevel(); } function playLetter(letter) { var locale = GCompris.ApplicationInfo.getVoicesLocale(items.locale) items.audioVoices.append(GCompris.ApplicationInfo.getAudioFilePath("voices-$CA/"+locale+"/alphabet/" + Core.getSoundFilenamForChar(letter))) } function focusTextInput() { if (!GCompris.ApplicationInfo.isMobile && items && items.textinput) items.textinput.forceActiveFocus(); }