diff --git a/src/activities/alphabetical_order/AlphabeticalOrder.qml b/src/activities/alphabetical_order/AlphabeticalOrder.qml index 3bba97990..511f7e0a1 100644 --- a/src/activities/alphabetical_order/AlphabeticalOrder.qml +++ b/src/activities/alphabetical_order/AlphabeticalOrder.qml @@ -1,767 +1,693 @@ /* 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: false property bool playLetter: false property double startTime property bool passedLevel: false } 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."), qsTr("You can press on the configuration button to select different options."), qsTr("If the OK button is activated, the level correctness will be checked only after pressing the OK button; else, if the answer is correct, the next level will be automatically loaded."), qsTr("If the 'easy mode' is activated, when dragging a letter to its right place, a sparkle effect will appear, otherwise the letter will glow in red."), qsTr("When pressing on a letter, a voice will spell it if the 'Play letter sound' is activated.") ] 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() items.passedLevel = true 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 var textAux2 = letter.text repeater.itemAt(i).text = textAux2 repeater.itemAt(index).text = textAux items.listModel.setProperty(i,"letter",textAux2) 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 var textAux2 = letter.text if (textAux1 != '_' && textAux2 != '_') { inputRepeater.itemAt(i).text = textAux2 items.listModelInput.setProperty(i,"letter",textAux2) repeater.itemAt(index).text = textAux1 items.listModel.setProperty(index,"letter",textAux1) if (items.easyMode) { if (textAux2 == Activity.model[index]) { particleLoader.item.burst(40) } else { failureAnimation.start() } } // 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 < items.repeater.count; i++) { // map the itemAt(i)'s coordinates to background coordinates to match the mouse coordinates var item = items.repeater.itemAt(i) var itemMapped = items.repeater.parent.mapToItem(background,item.x,item.y) // if the mouse click is released in the repeater area if (mouseMapped.x > 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 var textAux2 = missingLetter.text // if the letter at index i in the repeater is '_', then replace '_' with missingLetter.text if (textAux == '_') { repeater.itemAt(i).text = textAux2 items.listModel.setProperty(i,"letter",textAux2) 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 { repeater.itemAt(i).text = textAux2 items.listModel.setProperty(i,"letter",textAux2) inputRepeater.itemAt(index).text = textAux 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: { 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 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}) } // 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) } 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) { - background.locale = dataToSave["locale"]; items.okBoxChecked = dataToSave["okButton"] === "true" ? true : false items.easyMode = dataToSave["mode"] === "true" ? true : false items.playLetter = dataToSave["play"] === "true" ? true : false } } - 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,"okButton": items.okBoxChecked,"mode": items.easyMode,"play": items.playLetter} - - 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 6bd5d72b8..ed4353424 100644 --- a/src/activities/alphabetical_order/alphabetical_order.js +++ b/src/activities/alphabetical_order/alphabetical_order.js @@ -1,368 +1,314 @@ /* 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 alphabet = ['ab','cd','ef','gh'] +var alphabet = ['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 +var difficulty = 0 // 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 = 0 //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) 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 && items.passedLevel) { 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 } } else if (sum == 4) { if (progress[progress.length - 1] != 0 && progress[progress.length - 2] != 0) { if (difficulty <= 5) difficulty ++ } } else if (sum == 2) { if (difficulty >= 1) difficulty -- } else if (sum < 2) { if (difficulty >= 2) difficulty -= 2 else difficulty = 0 } } 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 if (items.passedLevel) { // 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 } items.passedLevel = false } // 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 } // remove first element in vector badAnsers badAnswers = badAnswers.slice(1,badAnswers.length) // 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) + solution = makeSolution(alphabet, 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++) { 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(); }