diff --git a/src/activities/enumerate/ActivityInfo.qml b/src/activities/enumerate/ActivityInfo.qml --- a/src/activities/enumerate/ActivityInfo.qml +++ b/src/activities/enumerate/ActivityInfo.qml @@ -37,4 +37,5 @@ credit: "" section: "math numeration" createdInVersion: 0 + levels: "1,2,3,4" } diff --git a/src/activities/enumerate/AnswerArea.qml b/src/activities/enumerate/AnswerArea.qml --- a/src/activities/enumerate/AnswerArea.qml +++ b/src/activities/enumerate/AnswerArea.qml @@ -37,15 +37,12 @@ } property string imgPath - // The backspace code coming from the virtual keyboard - property string backspaceCode // True when the value is entered correctly property bool valid: false property GCSfx audioEffects - Component.onCompleted: Activity.registerAnswerItem(answerBackground) onValidChanged: valid ? audioEffects.play("qrc:/gcompris/src/core/resource/sounds/win.wav") : null @@ -95,44 +92,19 @@ } Keys.onPressed: { - if(event.key === Qt.Key_Backspace) { - backspace() - } appendText(event.text) } - function backspace() { - userEntry.text = userEntry.text.slice(0, -1) - if(userEntry.text.length === 0) { - userEntry.text = "?" - valid = Activity.setUserAnswer(imgPath, -1) - return - } else { - valid = Activity.setUserAnswer(imgPath, parseInt(userEntry.text)) - return - } - } - function appendText(text) { - if(text === answerBackground.backspaceCode) { - backspace() - return - } - var number = parseInt(text) if(isNaN(number)) return if(userEntry.text === "?") { userEntry.text = "" } - if(userEntry.text.length >= 2) { - valid = false - return - } - - userEntry.text += text + userEntry.text = text valid = Activity.setUserAnswer(imgPath, parseInt(userEntry.text)) } diff --git a/src/activities/enumerate/Enumerate.qml b/src/activities/enumerate/Enumerate.qml --- a/src/activities/enumerate/Enumerate.qml +++ b/src/activities/enumerate/Enumerate.qml @@ -43,12 +43,57 @@ sourceSize.width: Math.max(parent.width, parent.height) Component.onCompleted: { + dialogActivityConfig.initialize() activity.start.connect(start) activity.stop.connect(stop) } onStart: { Activity.start(items); keyboard.populate(); } onStop: { Activity.stop() } + //instruction rectangle + Rectangle { + id: instruction + anchors { + top: parent.top + topMargin: 5 + horizontalCenter: parent.horizontalCenter + } + height: instructionTxt.contentHeight * 1.1 + width: Math.max(Math.min(parent.width * 0.8, instructionTxt.text.length * 10), parent.width * 0.3) + opacity: 0.8 + visible: items.levels + radius: 10 + border.width: 2 + z: instruction.opacity === 0 ? -10 : 10 + border.color: "#DDD" + color: "#373737" + + Behavior on opacity { PropertyAnimation { duration: 200 } } + + //shows/hides the Instruction + MouseArea { + anchors.fill: parent + onClicked: instruction.opacity = instruction.opacity == 0 ? 0.8 : 0 + } + + GCText { + id: instructionTxt + anchors { + top: parent.top + topMargin: 5 + horizontalCenter: parent.horizontalCenter + } + opacity: instruction.opacity + z: instruction.z + fontSize: smallSize + color: "white" + text: items.instructionText + horizontalAlignment: Text.AlignHCenter + width: parent.width * 0.8 + wrapMode: TextEdit.WordWrap + } + } + Keys.onDownPressed: { if(++answerColumn.currentIndex >= answerColumn.count) answerColumn.currentIndex = 0 @@ -65,8 +110,13 @@ property alias background: background property alias bar: bar property alias bonus: bonus + property alias okButton: okButton + property alias timer: timer property alias answerColumnModel: answerColumn.model property alias itemListModel: itemList.model + property string instructionText: "" + property alias score: score + property var levels: activity.datasetLoader.data.length !== 0 ? activity.datasetLoader.data : null } DropArea { @@ -84,26 +134,29 @@ sourceSize.width: Math.max(parent.width, parent.height) } - Column { - id: answer + GridView{ + id: answerColumn anchors { left: parent.left top: parent.top margins: 10 } - spacing: 5 - - Repeater { - id: answerColumn - property int currentIndex - - onModelChanged: currentIndex = count - 1 - AnswerArea { - imgPath: modelData - focus: true - backspaceCode: keyboard.backspace - audioEffects: activity.audioEffects - } + + height: cellHeight * 4; + width: cellWidth * 2 + cellWidth: Math.min(140 * ApplicationInfo.ratio, background.width / 4)+5; + cellHeight: cellWidth / 2; + flow: GridView.TopToBottom; + property int currentIndex + onModelChanged: { + currentIndex = count - 1 + Activity.registerAnswerItem(itemAt(1,1)) + } + + delegate: AnswerArea { + imgPath: modelData + focus: true + audioEffects: activity.audioEffects } add: Transition { @@ -147,31 +200,87 @@ { label: "6" }, { label: "7" }, { label: "8" }, - { label: "9" }, - { label: keyboard.backspace } + { label: "9" } ] ] } onKeypress: Activity.currentAnswerItem.appendText(text) onError: console.log("VirtualKeyboard error: " + msg); } + + DialogChooseLevel { + id: dialogActivityConfig + currentActivity: activity.activityInfo + onSaveData: { + levelFolder = dialogActivityConfig.chosenLevels + currentActivity.currentLevels = dialogActivityConfig.chosenLevels + ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels) + activity.focus = true + background.stop() + background.start() + } + onLoadData: { + if(activityData) { + Activity.initLevel() + } + } + onClose: { + home() + } + onStartActivity: { + background.start() + } + } + + Score { + id: score + anchors.top: okButton.bottom + anchors.bottom: keyboard.top + anchors.rightMargin: 10 * ApplicationInfo.ratio + } + DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar anchors.bottom: keyboard.top - content: BarEnumContent { value: help | home | level } + content: BarEnumContent { value: help | home | level | activityConfig } onHelpClicked: { displayDialog(dialogHelp) } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() + onActivityConfigClicked: { + displayDialog(dialogActivityConfig) + } + } + + BarButton { + id: okButton + anchors { + bottom: bar.top + right: parent.right + rightMargin: 9 * ApplicationInfo.ratio + bottomMargin: 9 * ApplicationInfo.ratio + } + source: "qrc:/gcompris/src/core/resource/bar_ok.svg" + sourceSize.width: 80 * ApplicationInfo.ratio + onClicked: Activity.triggerOkButton(); + } + + Keys.onReturnPressed: Activity.triggerOkButton() + Keys.onEnterPressed: Activity.triggerOkButton() + + Timer { + id: timer; + interval: 2000; + onTriggered: okButton.enabled = true; } Bonus { diff --git a/src/activities/enumerate/enumerate.js b/src/activities/enumerate/enumerate.js --- a/src/activities/enumerate/enumerate.js +++ b/src/activities/enumerate/enumerate.js @@ -26,8 +26,13 @@ var url = "qrc:/gcompris/src/activities/enumerate/resource/" var url2 = "qrc:/gcompris/src/activities/algorithm/resource/" var items -var currentLevel = 0 -var numberOfLevel = 9 +var maxSubLevel +var dataset +var currentLevel +var currentSubLevel +var numberOfLevel +var numberOfItemType +var numberOfItemMax var itemIcons = [ url2 + "apple.svg", url2 + "banana.svg", @@ -61,69 +66,18 @@ } function initLevel() { + if(items.levels) + items.instructionText = items.levels[currentLevel].objective items.bar.level = currentLevel + 1 + dataset = items.levels + numberOfLevel = dataset.length + currentSubLevel = 0 cleanUp() - - var numberOfItemType - var numberOfItemMax - - switch(currentLevel) - { - case 0: - numberOfItemType = 1; - numberOfItemMax = 5; - break; - case 1: - numberOfItemType = 2; - numberOfItemMax = 5; - break; - case 2: - numberOfItemType = 3; - numberOfItemMax = 4; - break; - case 3: - numberOfItemType = 3; - numberOfItemMax = 5; - break; - case 4: - numberOfItemType = 4; - numberOfItemMax = 5; - break; - case 5: - numberOfItemType = 4; - numberOfItemMax = 6; - break; - case 6: - numberOfItemType = 5; - numberOfItemMax = 5; - break; - case 7: - numberOfItemType = 4; - numberOfItemMax = 6; - break; - case 8: - numberOfItemType = 3; - numberOfItemMax = 8; - break; - default: - numberOfItemType = 2; - numberOfItemMax = 9; - } - - itemIcons = Core.shuffle(itemIcons) - var enumItems = new Array() - var types = new Array() - - for(var type = 0; type < numberOfItemType; type++) { - var nbItems = getRandomInt(1, numberOfItemMax) - for(var j = 0; j < nbItems; j++) { - enumItems.push(itemIcons[type]) - } - answerToFind[itemIcons[type]] = nbItems - types.push(itemIcons[type]) - } - items.answerColumnModel = types - items.itemListModel = enumItems + numberOfItemType = dataset[currentLevel].numberOfItemType + numberOfItemMax = dataset[currentLevel].numberOfItemMax + maxSubLevel = dataset[currentLevel].sublevels + items.score.numberOfSubLevels = maxSubLevel; + initSubLevel(); } function nextLevel() { @@ -147,17 +101,17 @@ function setUserAnswer(imgPath, userValue) { userAnswers[imgPath] = userValue - checkAnswers() return userAnswers[imgPath] === answerToFind[imgPath] } function checkAnswers() { for (var key in answerToFind) { if(userAnswers[key] !== answerToFind[key]) { - return; + items.bonus.bad("smiley") + return } } - items.bonus.good("smiley") + nextSubLevel() } function getRandomInt(min, max) { @@ -170,3 +124,38 @@ currentAnswerItem = item item.forceActiveFocus() } + +function initSubLevel() { + itemIcons = Core.shuffle(itemIcons) + items.score.currentSubLevel = currentSubLevel + 1; + var enumItems = new Array() + var types = new Array() + for(var type = 0; type < numberOfItemType; type++) { + var nbItems = getRandomInt(1, numberOfItemMax) + for(var j = 0; j < nbItems; j++) { + enumItems.push(itemIcons[type]) + } + answerToFind[itemIcons[type]] = nbItems + types.push(itemIcons[type]) + } + items.answerColumnModel = types + items.itemListModel = enumItems +} + +function nextSubLevel() { + if( ++currentSubLevel >= maxSubLevel) { + items.bonus.good("smiley") + currentSubLevel = 0; + } else + items.score.playWinAnimation(); + cleanUp(); + initSubLevel(); +} + +function triggerOkButton() { + if(items.okButton.enabled === true) { + items.okButton.enabled = false + checkAnswers() + items.timer.start() + } +} diff --git a/src/activities/enumerate/resource/1/Data.qml b/src/activities/enumerate/resource/1/Data.qml new file mode 100644 --- /dev/null +++ b/src/activities/enumerate/resource/1/Data.qml @@ -0,0 +1,52 @@ +/* GCompris - Data.qml + * + * Copyright (C) 2020 Shubham Mishra + * + * Authors: + * Shubham Mishra + * + * 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 "../../../../core" + +Dataset { + objective: qsTr("Enumerate up to 4 fruits") + difficulty: 1 + data: [ + { + "objective": qsTr("Enumerate 1 fruit"), + "sublevels" : "2", + "numberOfItemType" : 1, + "numberOfItemMax" : 1 + }, + { + "objective": qsTr("Enumerate up to 2 fruits"), + "sublevels" : "3", + "numberOfItemType" : 1, + "numberOfItemMax" : 2 + }, + { + "objective": qsTr("Enumerate up to 3 fruits"), + "sublevels" : "4", + "numberOfItemType" : 1, + "numberOfItemMax" : 3 + }, + { + "objective": qsTr("Enumerate up to 4 fruits"), + "sublevels" : "4", + "numberOfItemType" : 1, + "numberOfItemMax" : 4 + } + ] +} diff --git a/src/activities/enumerate/resource/2/Data.qml b/src/activities/enumerate/resource/2/Data.qml new file mode 100644 --- /dev/null +++ b/src/activities/enumerate/resource/2/Data.qml @@ -0,0 +1,64 @@ +/* GCompris - Data.qml + * + * Copyright (C) 2020 Shubham Mishra + * + * Authors: + * Shubham Mishra + * + * 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 "../../../../core" + +Dataset { + objective: qsTr("Group 2 types of fruits and Enumerate each group (6 fruits max)") + difficulty: 2 + data: [ + { + "objective": qsTr("Enumerate up to 4 fruits"), + "sublevels" : "4", + "numberOfItemType" : 1, + "numberOfItemMax" : 4 + }, + { + "objective": qsTr("Group 2 types of fruits and enumerate each group (4 fruits max)"), + "sublevels" : "4", + "numberOfItemType" : 2, + "numberOfItemMax" : 4 + }, + { + "objective": qsTr("Enumerate up to 5 fruits"), + "sublevels" : "5", + "numberOfItemType" : 1, + "numberOfItemMax" : 5 + }, + { + "objective": qsTr("Group 2 types of fruits and enumerate each group (5 fruits max)"), + "sublevels" : "5", + "numberOfItemType" : 2, + "numberOfItemMax" : 5 + }, + { + "objective": qsTr("Enumerate up to 6 fruits"), + "sublevels" : "6", + "numberOfItemType" : 1, + "numberOfItemMax" : 6 + }, + { + "objective": qsTr("Group 2 types of fruits and enumerate each group (6 fruits max)"), + "sublevels" : "6", + "numberOfItemType" : 2, + "numberOfItemMax" : 6 + } + ] +} diff --git a/src/activities/enumerate/resource/3/Data.qml b/src/activities/enumerate/resource/3/Data.qml new file mode 100644 --- /dev/null +++ b/src/activities/enumerate/resource/3/Data.qml @@ -0,0 +1,64 @@ +/* GCompris - Data.qml + * + * Copyright (C) 2020 Shubham Mishra + * + * Authors: + * Shubham Mishra + * + * 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 "../../../../core" + +Dataset { + objective: qsTr("Group 3 types of fruits and enumerate each group (6 fruits max)") + difficulty: 2 + data: [ + { + "objective": qsTr("Group 2 types of fruits and enumerate each group (4 fruits max)"), + "sublevels" : "4", + "numberOfItemType" : 2, + "numberOfItemMax" : 4 + }, + { + "objective": qsTr("Group 3 types of fruits and enumerate each group (4 fruits max)"), + "sublevels" : "4", + "numberOfItemType" : 3, + "numberOfItemMax" : 4 + }, + { + "objective": qsTr("Group 2 types of fruits and enumerate each group (5 fruits max)"), + "sublevels" : "5", + "numberOfItemType" : 2, + "numberOfItemMax" : 5 + }, + { + "objective": qsTr("Group 3 types of fruits and enumerate each group (5 fruits max)"), + "sublevels" : "5", + "numberOfItemType" : 3, + "numberOfItemMax" : 5 + }, + { + "objective": qsTr("Group 2 types of fruits and enumerate each group (6 fruits max)"), + "sublevels" : "6", + "numberOfItemType" : 2, + "numberOfItemMax" : 6 + }, + { + "objective": qsTr("Group 3 types of fruits and enumerate each group (6 fruits max)"), + "sublevels" : "6", + "numberOfItemType" : 3, + "numberOfItemMax" : 6 + } + ] +} diff --git a/src/activities/enumerate/resource/4/Data.qml b/src/activities/enumerate/resource/4/Data.qml new file mode 100644 --- /dev/null +++ b/src/activities/enumerate/resource/4/Data.qml @@ -0,0 +1,100 @@ +/* GCompris - Data.qml + * + * Copyright (C) 2020 Shubham Mishra + * + * Authors: + * Shubham Mishra + * + * 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 "../../../../core" + +Dataset { + objective: qsTr("Group 5 types of fruits and enumerate each group (9 fruits max)") + difficulty: 3 + data: [ + { + "objective": qsTr("Group 3 types of fruits and enumerate each group (4 fruits max)"), + "sublevels" : "4", + "numberOfItemType" : 3, + "numberOfItemMax" : 4 + }, + { + "objective": qsTr("Group 4 types of fruits and enumerate each group (4 fruits max)"), + "sublevels" : "4", + "numberOfItemType" : 4, + "numberOfItemMax" : 4 + }, + { + "objective": qsTr("Group 4 types of fruits and enumerate each group (5 fruits max)"), + "sublevels" : "5", + "numberOfItemType" : 4, + "numberOfItemMax" : 5 + }, + { + "objective": qsTr("Group 5 types of fruits and enumerate each group (5 fruits max)"), + "sublevels" : "5", + "numberOfItemType" : 5, + "numberOfItemMax" : 5 + }, + { + "objective": qsTr("Group 4 types of fruits and enumerate each group (6 fruits max)"), + "sublevels" : "6", + "numberOfItemType" : 4, + "numberOfItemMax" : 6 + }, + { + "objective": qsTr("Group 5 types of fruits and enumerate each group (6 fruits max)"), + "sublevels" : "6", + "numberOfItemType" : 5, + "numberOfItemMax" : 6 + }, + { + "objective": qsTr("Group 4 types of fruits and enumerate each group (7 fruits max)"), + "sublevels" : "7", + "numberOfItemType" : 4, + "numberOfItemMax" : 7 + }, + { + "objective": qsTr("Group 5 types of fruits and enumerate each group (7 fruits max)"), + "sublevels" : "7", + "numberOfItemType" : 5, + "numberOfItemMax" : 7 + }, + { + "objective": qsTr("Group 4 types of fruits and enumerate each group (8 fruits max)"), + "sublevels" : "8", + "numberOfItemType" : 4, + "numberOfItemMax" : 8 + }, + { + "objective": qsTr("Group 5 types of fruits and enumerate each group (8 fruits max)"), + "sublevels" : "8", + "numberOfItemType" : 5, + "numberOfItemMax" : 8 + }, + { + "objective": qsTr("Group 4 types of fruits and enumerate each group (9 fruits max)"), + "sublevels" : "9", + "numberOfItemType" : 4, + "numberOfItemMax" : 9 + }, + { + "objective": qsTr("Group 5 types of fruits and enumerate each group (9 fruits max)"), + "sublevels" : "9", + "numberOfItemType" : 5, + "numberOfItemMax" : 9 + } + ] +}