diff --git a/src/activities/calendar/calendar.js b/src/activities/calendar/calendar.js index edef10d82..7a908d26f 100644 --- a/src/activities/calendar/calendar.js +++ b/src/activities/calendar/calendar.js @@ -1,145 +1,145 @@ /* GCompris - calendar.js * * Copyright (C) 2017 Amit Sagtani * * Authors: * Amit Sagtani * * 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.6 as Quick .import QtQml 2.2 as Qml .import GCompris 1.0 as GCompris //for ApplicationInfo .import "qrc:/gcompris/src/core/core.js" as Core var currentLevel = 0 var numberOfLevel var currentSubLevel = 1 var currentDataSet var currentLevelConfig var dataset var items var daySelected = 1 var monthSelected = 2 var yearSelected = 2018 var dayOfWeekSelected var minRange //sum of min. visible month and year on calendar for navigation bar next/prev button visibility. var maxRange //sum of max. visible month and year on calendar for navigation bar next/prev button visibility. var correctAnswer var mode function start(items_, dataset_) { items = items_ dataset = dataset_.get() numberOfLevel = dataset.length currentLevel = 0 if(Qt.locale(GCompris.ApplicationSettings.locale).firstDayOfWeek == Qml.Locale.Monday) { items.daysOfTheWeekModel.move(0, items.daysOfTheWeekModel.count - 1, 1) } initLevel(); } function stop() { } function initLevel() { currentSubLevel = 1; items.bar.level = currentLevel + 1 currentLevelConfig = dataset[currentLevel][0][0] setCalendarConfigurations() initQuestion(); } function nextLevel() { if(numberOfLevel <= ++currentLevel) { currentLevel = 0 } initLevel(); } function previousLevel() { if(--currentLevel < 0) { currentLevel = numberOfLevel - 1 } initLevel(); } // Configure calendar properties for every level. function setCalendarConfigurations() { minRange = Number(currentLevelConfig["minimumDate"].slice(5,7)) + Number(currentLevelConfig["minimumDate"].slice(0,4)) - 1; maxRange = Number(currentLevelConfig["maximumDate"].slice(5,7)) + Number(currentLevelConfig["maximumDate"].slice(0,4)) - 1; mode = currentLevelConfig["mode"] items.calendar.navigationBarVisible = currentLevelConfig["navigationBarVisible"] items.calendar.minimumDate = currentLevelConfig["minimumDate"] items.calendar.maximumDate = currentLevelConfig["maximumDate"] items.calendar.visibleYear = currentLevelConfig["visibleYear"] yearSelected = currentLevelConfig["visibleYear"] items.calendar.visibleMonth = currentLevelConfig["visibleMonth"] monthSelected = currentLevelConfig["visibleMonth"] items.answerChoices.visible = (mode === "findDayOfWeek") ? true : false items.okButton.visible = !items.answerChoices.visible currentDataSet = dataset[currentLevel][1] currentDataSet = Core.shuffle(currentDataSet) items.score.numberOfSubLevels = currentDataSet.length items.score.currentSubLevel = currentSubLevel } function initQuestion() { if(currentDataSet.length < currentSubLevel) { items.bonus.good("lion") } else { items.score.currentSubLevel = currentSubLevel items.questionItem.text = currentDataSet[currentSubLevel-1]["question"] correctAnswer = currentDataSet[currentSubLevel-1]["answer"] } } function updateScore(isCorrectAnswer) { if(isCorrectAnswer) { items.questionDelay.start() items.okButtonParticles.burst(20) items.score.playWinAnimation() currentSubLevel++; } else - items.bonus.bad("lion") + items.bonus.bad("lion", items.bonus.checkAnswer) } function checkAnswer() { var isCorrectAnswer = false // For levels having questions based on day of week only. if(mode === "findDayOfWeek") { if(dayOfWeekSelected === correctAnswer["dayOfWeek"]) { isCorrectAnswer = true } } // For levels having question based on month only. else if(mode === "findMonthOnly") { if(correctAnswer["month"].indexOf(monthSelected) >= 0) { isCorrectAnswer = true } } // For levels having questions based on dayOfWeek, month and year. else if(mode !== "findDayOfWeek") { if(monthSelected === correctAnswer["month"] && daySelected === correctAnswer["day"] && yearSelected === correctAnswer["year"]) { isCorrectAnswer = true } } updateScore(isCorrectAnswer) } diff --git a/src/activities/categorization/categorization.js b/src/activities/categorization/categorization.js index 1d733e538..7f16c6e3d 100644 --- a/src/activities/categorization/categorization.js +++ b/src/activities/categorization/categorization.js @@ -1,305 +1,305 @@ /* GCompris - categorization.js * * Copyright (C) 2016 Divyam Madaan * * Authors: * Divyam Madaan * * 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.6 as Quick .import GCompris 1.0 as GCompris .import "qrc:/gcompris/src/core/core.js" as Core var categoryModelIndex = 0; var currentSubLevel = 0; var items var lessons var categories var images var items var currentLevel = 1 var numberOfLevel var index var imagesData = [] var categoriesData = [] var expertCategories = [] var boardsUrl var answerTable = {} var totalImages var fileName = ":/gcompris/data/words/animals/camel.jpg" function init(items_,boardsUrl_) { boardsUrl = boardsUrl_ items = items_ items.menuModel.clear() currentSubLevel = 0 } function start() { categoriesData = [] items.categoryReview.stop() var isEmbeddedMode = items.file.exists(fileName) ? true : false items.categoriesFallback = !isEmbeddedMode var categoriesFilename; var categoryDataset = items.categoryReview.categoryDataset var categoryLists = items.categories for(var i = 0; i < categoryLists.length; i++) { categoriesFilename = "qrc" + boardsUrl + categoryLists[i] categoryDataset.source = categoriesFilename if(isEmbeddedMode || categoryDataset.item.isEmbedded) { categoriesData.push(categoryDataset.item) } } lessons = getAllLessons(categoriesData) categories = getCategoryModel(categoriesData) addPropertiesToCategories(categories) items.menuModel.append(categories) savedPropertiesToCategories(items.dialogActivityConfig.dataToSave) sortByFavorites() items.menuScreen.start() } // Inserts specific properties to the categories function addPropertiesToCategories(categories) { for (var i = 0; i < categories.length; i++) { categories[i]['name'] = categories[i].name categories[i]['image'] = categories[i].image categories[i]['favorite'] = false categories[i]['categoryIndex'] = i } } // Return all the properties we have to save function categoriesToSavedProperties() { var props = {} for(var i = 0; i < items.menuModel.count; i++) { var category = items.menuModel.get(i) props[category.name] = { 'favorite': category['favorite'] } } return props } // Update the categories based on a previous saving function savedPropertiesToCategories(dataToSave) { var props = dataToSave["data"] for(var i = 0; i < items.menuModel.count; i++) { var category = items.menuModel.get(i) var categoryname = category.name if(props && props[category.name]) { category['favorite'] = props[category.name].favorite } else { category['favorite'] = false } } } function sortByFavorites() { for(var i = 0; i < items.menuModel.count; i++) { if(items.menuModel.get(i)['favorite']) { items.menuModel.move(i, 0, 1); } } } function launchMenuScreen() { items.categoryReview.stop() items.menuScreen.start() } function startCategory() { items.categoryReview.start() items.menuScreen.stop() currentLevel = 0 items.bar.level = 0 initLevel() } function storeCategoriesLevels(index_) { index = index_ currentLevel = 0 numberOfLevel = 0 initLevel() } function initLevel() { items.bar.level = currentLevel + 1 items.categoryReview.score.currentSubLevel = 0 items.instructionsVisible = true getCategoryLevels(index); numberOfLevel = items.details.length; items.categoryReview.leftZone.clear(); items.categoryReview.rightZone.clear(); items.categoryReview.start(); items.menuScreen.stop() } function nextLevel() { if(numberOfLevel <= ++currentLevel) { currentLevel = 0 } items.categoryReview.score.currentSubLevel = 0 initLevel(index); getCategoryLevels(); } function previousLevel() { if(--currentLevel < 0) { currentLevel = numberOfLevel - 1 } initLevel(index); getCategoryLevels(); } // Checks if all the items are dragged and dropped in the correct or incorrect area. function allPlaced() { items.categoryReview.score.currentSubLevel = 0; for(var i = 0 ; i < items.categoryReview.leftZone.count; ++i) { for(var answer in answerTable) { var droppedZoneItem = items.categoryReview.leftZone.get(i) if(answer === droppedZoneItem.name && ((droppedZoneItem.droppedZone === "right" && answerTable[answer]) || (droppedZoneItem.droppedZone === "left" && !answerTable[answer]))) items.categoryReview.score.currentSubLevel ++ } } for(var i = 0 ; i < items.categoryReview.rightZone.count; ++i) { for(var answer in answerTable) { var droppedZoneItem = items.categoryReview.rightZone.get(i) if(answer === droppedZoneItem.name && ((droppedZoneItem.droppedZone === "right" && answerTable[answer]) || (droppedZoneItem.droppedZone === "left" && !answerTable[answer]))) items.categoryReview.score.currentSubLevel ++ } } if(items.categoryReview.score.currentSubLevel === totalImages) items.bonus.good("flower") else - items.bonus.bad("flower") + items.bonus.bad("flower", items.bonus.checkAnswer) } // Save properties to lessons function getCategoryLevels() { var randomGood = 0; var randomBad = 0; items.categoryReview.middleZone.clear() /* If easy or medium mode is selected, store the details of levels of category of that respective index in items.details. */ if(items.mode !== "expert") { items.details = lessons[index].map(function(ele) { return { "instructions": ele.instructions, "image": ele.image, "numberOfGood": ele.maxNumberOfGood, "numberofBad": ele.maxNumberOfBad, "categoryImages": ele.levelImages ,"good": ele.good, "bad": ele.bad ,"prefix": ele.prefix } }); } // If expert mode is selected, select a random level (selectedLevel) from a random category (selectedCategory) else if(items.mode === "expert") { var selectedCategory = Math.floor(Math.random() * expertCategories.length) var selectedLevel = [] selectedLevel[0] = expertCategories[selectedCategory][Math.floor(Math.random() * expertCategories[selectedCategory].length)] items.details = selectedLevel.map(function(ele) { return { "instructions": ele.instructions, "image": ele.image, "numberOfGood": ele.maxNumberOfGood, "numberofBad": ele.maxNumberOfBad, "categoryImages": ele.levelImages ,"good": ele.good, "bad": ele.bad, "prefix": ele.prefix } }); } var imagesPrefix = items.details[items.bar.level - 1].prefix // Good set of images var goodImages = items.details[items.bar.level - 1].good var numberOfGood = Math.min(goodImages.length,items.details[items.bar.level-1].numberOfGood); var goodZoneImages = goodImages.map(function(obj) { obj = imagesPrefix + obj return { "name": obj, "isRight": true } }); goodZoneImages = goodZoneImages.splice(0, numberOfGood); // Bad set of images var badImages = items.details[items.bar.level - 1].bad var badZoneImages = badImages.map(function(obj) { obj = imagesPrefix + obj return { "name": obj, "isRight": false } }); var numberOfBad = Math.min(badImages.length,items.details[items.bar.level-1].numberofBad); badZoneImages = badZoneImages.splice(0, numberOfBad); // Concat both set of images(good and bad) in allImages and store in middleZone model var allImages = goodZoneImages.concat(badZoneImages); Core.shuffle(allImages); for(var i = 0; i < allImages.length; i++) { answerTable[allImages[i].name] = allImages[i].isRight items.categoryReview.middleZone.append({"isRight": allImages[i].isRight,"name": allImages[i].name}) } totalImages = allImages.length items.categoryReview.score.numberOfSubLevels = totalImages } // get categories details from the complete dataset function getCategoryModel(dataset) { var categories = [] for (var c = 0; c < dataset.length; c++) { categories.push({ 'name': dataset[c].levels[0].name, 'image': dataset[c].levels[0].image, 'index': c }) } return categories } // get all the content (levels) from the category in dataset function getAllLessons(dataset) { var lessons = [] for(var c = 0; c < dataset.length; c++) { lessons.push(dataset[c].levels[0].content) if(dataset[c].allowExpertMode) { expertCategories.push(dataset[c].levels[0].content) } } return lessons } function setValues() { items.categoryReview.leftAreaContainsDrag = false items.categoryReview.rightAreaContainsDrag = false } function isDragInLeftArea(leftAreaRightBorderPos, elementRightPos) { if(elementRightPos <= leftAreaRightBorderPos) return true; else return false; } function isDragInRightArea(rightAreaLeftBorderPos, elementLeftPos) { if((rightAreaLeftBorderPos <= elementLeftPos)) return true; else return false; } function dropControl(sourcePosition, destinationPosition, image, index) { var destinationZone = destinationPosition === "left" ? items.categoryReview.leftZone : destinationPosition === "right" ? items.categoryReview.rightZone : items.categoryReview.middleZone var sourceZone = sourcePosition === "left" ? items.categoryReview.leftZone : sourcePosition === "right" ? items.categoryReview.rightZone : items.categoryReview.middleZone destinationZone.append({"name": image, "droppedZone": destinationPosition}) sourceZone.remove(index) } diff --git a/src/activities/digital_electricity/digital_electricity.js b/src/activities/digital_electricity/digital_electricity.js index 73e02b42d..ecd784222 100644 --- a/src/activities/digital_electricity/digital_electricity.js +++ b/src/activities/digital_electricity/digital_electricity.js @@ -1,657 +1,657 @@ /* GCompris - digital_electricity.js * * Copyright (C) 2016 Pulkit Gupta * * Authors: * Bruno Coudoin (GTK+ version) * Pulkit Gupta (Qt Quick port) * Rudra Nil Basu (Qt Quick port) * Timothée Giet (mouse drag refactoring) * * 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.6 as Quick var currentLevel = 1 var numberOfLevel var items var url = "qrc:/gcompris/src/activities/digital_electricity/resource/" var toolDelete var toolDeleteSticky var selectedIndex var animationInProgress var selectedTerminal var deletedIndex = [] var components = [] var connected = [] var determiningComponents = [] var processingAnswer var currentZoom var maxZoom = 0.375 var minZoom = 0.125 var defaultZoom = 0.25 var zoomStep = 0.0625 var direction = { LEFT: -1, RIGHT: 1, UP: -2, DOWN: 2 } var viewPort = { leftExtreme: 0, rightExtreme: 1, topExtreme: 0, bottomExtreme: 1, leftEdge: 0, topEdge: 0 } function start(items_) { items = items_ currentLevel = 1 numberOfLevel = items.tutorialDataset.tutorialLevels.length initLevel() } function stop() { for(var i = 0 ; i < components.length ; ++i) { var j for(j = 0 ; j < deletedIndex.length ; ++j) { if(deletedIndex[j] == i) break } if(j == deletedIndex.length) removeComponent(i) } } function initLevel() { items.bar.level = currentLevel items.availablePieces.view.currentDisplayedGroup = 0 items.availablePieces.view.previousNavigation = 1 items.availablePieces.view.nextNavigation = 1 deletedIndex = [] components = [] connected = [] determiningComponents = [] animationInProgress = false toolDelete = false toolDeleteSticky = false deselect() updateToolTip("") items.availablePieces.hideToolbar() currentZoom = defaultZoom items.availablePieces.zoomInBtn.state = "canZoomIn" items.availablePieces.zoomOutBtn.state = "canZoomOut" viewPort.leftEdge = 0 viewPort.topEdge = 0 items.playArea.x = items.mousePan.drag.maximumX items.playArea.y = items.mousePan.drag.maximumY if (!items.isTutorialMode) { items.tutorialInstruction.index = -1 loadFreeMode() } else { // load tutorial levels from dataset processingAnswer = false var levelProperties = items.tutorialDataset.tutorialLevels[currentLevel - 1] for (var i = 0; i < levelProperties.inputComponentList.length; i++) { var currentInputComponent = levelProperties.inputComponentList[i] items.availablePieces.model.append( { "imgName": currentInputComponent.imageName, "componentSrc": currentInputComponent.componentSource, "imgWidth": currentInputComponent.width, "imgHeight": currentInputComponent.height, "toolTipText": currentInputComponent.toolTipText }) } for (var i = 0; i < levelProperties.playAreaComponentList.length; i++) { var index = components.length var currentPlayAreaComponent = levelProperties.playAreaComponentList[i] var staticElectricalComponent = Qt.createComponent("qrc:/gcompris/src/activities/digital_electricity/components/" + currentPlayAreaComponent.componentSource) components[index] = staticElectricalComponent.createObject( items.playArea, { "index": index, "posX": levelProperties.playAreaComponentPositionX[i] * currentZoom, "posY": levelProperties.playAreaComponentPositionY[i] * currentZoom, "imgSrc": currentPlayAreaComponent.imageName, "toolTipTxt": currentPlayAreaComponent.toolTipText, "imgWidth": currentPlayAreaComponent.width * currentZoom, "imgHeight": currentPlayAreaComponent.height * currentZoom, "destructible": false }); } var _determiningComponentsIndex = levelProperties.determiningComponentsIndex for (var i = 0; i < _determiningComponentsIndex.length; i++) { determiningComponents[determiningComponents.length] = components[_determiningComponentsIndex[i]] } // creating wires for (i = 0; i < levelProperties.wires.length; i++) { var terminal_number = levelProperties.wires[i][1] var outTerminal = components[levelProperties.wires[i][0]].outputTerminals.itemAt(terminal_number) terminal_number = levelProperties.wires[i][3] var inTerminal = components[levelProperties.wires[i][2]].inputTerminals.itemAt(terminal_number) createWire(inTerminal, outTerminal, false) } if (levelProperties.introMessage.length != 0) { items.tutorialInstruction.index = 0 items.tutorialInstruction.intro = levelProperties.introMessage } else { items.tutorialInstruction.index = -1 } } } function loadFreeMode() { var componentList = items.tutorialDataset.componentList for (var i = 0; i < componentList.length; i++) { items.availablePieces.model.append( { "imgName": componentList[i].imageName, "componentSrc": componentList[i].componentSource, "imgWidth": componentList[i].width, "imgHeight": componentList[i].height, "toolTipText": componentList[i].toolTipText }) } } function checkAnswer() { if (processingAnswer) return processingAnswer = true var problemType = items.tutorialDataset.tutorialLevels[currentLevel - 1].type var levelProperties = items.tutorialDataset.tutorialLevels[currentLevel - 1] if (problemType == items.tutorialDataset.problemType.lightTheBulb) { if (determiningComponents[0].inputTerminals.itemAt(0).value == 1) { items.bonus.good('tux') } else { - items.bonus.bad('tux') + items.bonus.bad('tux', items.bonus.checkAnswer) processingAnswer = false } } else if (problemType == items.tutorialDataset.problemType.equation1Variable) { var switch1 = determiningComponents[0] var digitalLight = determiningComponents[1] var switch1InitialState = switch1.imgSrc for (var A = 0; A <= 1; A++) { switch1.imgSrc = A == 1 ? "switchOn.svg" : "switchOff.svg" updateComponent(switch1.index) var operationResult = !A if (operationResult != digitalLight.inputTerminals.itemAt(0).value) { switch1.imgSrc = switch1InitialState updateComponent(switch1.index) - items.bonus.bad('tux') + items.bonus.bad('tux', items.bonus.checkAnswer) processingAnswer = false return } } items.bonus.good('tux') } else if (problemType == items.tutorialDataset.problemType.equation2Variables) { var digitalLight = determiningComponents[determiningComponents.length - 1] var switch1 = determiningComponents[0] var switch2 = determiningComponents[1] var switch1InitialState = switch1.imgSrc var switch2InitialState = switch2.imgSrc for (var A = 0; A <= 1; A++) { for (var B = 0; B <= 1; B++) { switch1.imgSrc = A == 1 ? "switchOn.svg" : "switchOff.svg" switch2.imgSrc = B == 1 ? "switchOn.svg" : "switchOff.svg" updateComponent(switch1.index) updateComponent(switch2.index) var operationResult = levelProperties.result(A, B) if (operationResult != digitalLight.inputTerminals.itemAt(0).value) { switch1.imgSrc = switch1InitialState switch2.imgSrc = switch2InitialState updateComponent(switch1.index) updateComponent(switch2.index) - items.bonus.bad('tux') + items.bonus.bad('tux', items.bonus.checkAnswer) processingAnswer = false return } } } items.bonus.good('tux') } else if (problemType == items.tutorialDataset.problemType.equation3Variables) { var switch1 = determiningComponents[0] var switch2 = determiningComponents[1] var switch3 = determiningComponents[2] var digitalLight = determiningComponents[3] var switch1InitialState = switch1.imgSrc var switch2InitialState = switch2.imgSrc var switch3InitialState = switch3.imgSrc for (var A = 0; A <= 1; A++) { for (var B = 0; B <= 1; B++) { for (var C = 0; C <= 1; C++) { switch1.imgSrc = A == 1 ? "switchOn.svg" : "switchOff.svg" switch2.imgSrc = B == 1 ? "switchOn.svg" : "switchOff.svg" switch3.imgSrc = C == 1 ? "switchOn.svg" : "switchOff.svg" updateComponent(switch1.index) updateComponent(switch2.index) updateComponent(switch3.index) var operationResult = levelProperties.result(A, B, C) if (operationResult != digitalLight.inputTerminals.itemAt(0).value) { switch1.imgSrc = switch1InitialState switch2.imgSrc = switch2InitialState switch3.imgSrc = switch3InitialState updateComponent(switch1.index) updateComponent(switch2.index) updateComponent(switch3.index) processingAnswer = false - items.bonus.bad('tux') + items.bonus.bad('tux', items.bonus.checkAnswer) return } } } } items.bonus.good('tux') } else if (problemType == items.tutorialDataset.problemType.others) { if (currentLevel == 20) { var bcdToSevenSegment = determiningComponents[0] var decimalValue = bcdToSevenSegment.inputTerminals.itemAt(3).value + (bcdToSevenSegment.inputTerminals.itemAt(2).value * 2) + (bcdToSevenSegment.inputTerminals.itemAt(1).value * 4) + (bcdToSevenSegment.inputTerminals.itemAt(0).value * 8) if (decimalValue == 6) { items.bonus.good('tux') return } - items.bonus.bad('tux') + items.bonus.bad('tux', items.bonus.checkAnswer) processingAnswer = false return } else if (currentLevel == 21) { var bcdCounter = determiningComponents[0] var bcdOutput = bcdCounter.outputTerminals.itemAt(3).value + bcdCounter.outputTerminals.itemAt(2).value * 2 + bcdCounter.outputTerminals.itemAt(1).value * 4 + bcdCounter.outputTerminals.itemAt(0).value * 8 var bcdToSevenSegment = determiningComponents[1] var decimalValue = bcdToSevenSegment.inputTerminals.itemAt(3).value + (bcdToSevenSegment.inputTerminals.itemAt(2).value * 2) + (bcdToSevenSegment.inputTerminals.itemAt(1).value * 4) + (bcdToSevenSegment.inputTerminals.itemAt(0).value * 8) if (bcdCounter.inputTerminals.itemAt(0).wires.length == 0 || bcdCounter.outputTerminals.itemAt(0).wires.length == 0 || bcdCounter.outputTerminals.itemAt(1).wires.length == 0 || bcdCounter.outputTerminals.itemAt(2).wires.length == 0 || bcdCounter.outputTerminals.itemAt(3).wires.length == 0) { items.bonus.bad('tux') processingAnswer = false return } if ((bcdOutput == decimalValue) && (bcdCounter.inputTerminals.itemAt(0).wires.length != 0) ) { items.bonus.good('tux') return } - items.bonus.bad('tux') + items.bonus.bad('tux', items.bonus.checkAnswer) processingAnswer = false } } } function zoomIn() { var previousZoom = currentZoom currentZoom += zoomStep if (currentZoom > maxZoom) currentZoom = maxZoom var zoomRatio = currentZoom / previousZoom updateComponentDimension(zoomRatio) if (currentZoom == maxZoom) { items.availablePieces.zoomInBtn.state = "cannotZoomIn" } else { items.availablePieces.zoomInBtn.state = "canZoomIn" } items.availablePieces.zoomOutBtn.state = "canZoomOut" if (items.zoomLvl < 0.5) { items.zoomLvl += 0.125 } } function zoomOut() { var previousZoom = currentZoom currentZoom -= zoomStep if (currentZoom < minZoom) currentZoom = minZoom var zoomRatio = currentZoom / previousZoom updateComponentDimension(zoomRatio) if (currentZoom == minZoom) { items.availablePieces.zoomOutBtn.state = "cannotZoomOut" } else { items.availablePieces.zoomOutBtn.state = "canZoomOut" } items.availablePieces.zoomInBtn.state = "canZoomIn" if (items.zoomLvl > 0) { items.zoomLvl -= 0.125 } } function updateComponentDimension(zoomRatio) { for (var i = 0; i < components.length; i++) { components[i].posX *= zoomRatio components[i].posY *= zoomRatio components[i].imgWidth *= zoomRatio components[i].imgHeight *= zoomRatio } } function nextLevel() { if(numberOfLevel < ++currentLevel) { currentLevel = 1 } reset(); } function previousLevel() { if(--currentLevel < 1) { currentLevel = numberOfLevel } reset(); } function reset() { stop() items.availablePieces.model.clear() initLevel() } // Creates component from ListWidget to the drawing board area function createComponent(x, y, componentIndex) { x = x / items.playArea.width y = y / items.playArea.height var index if(deletedIndex.length > 0) { index = deletedIndex[deletedIndex.length - 1] deletedIndex.pop() } else index = components.length var component = items.availablePieces.repeater.itemAt(componentIndex) var electricComponent = Qt.createComponent("qrc:/gcompris/src/activities/digital_electricity/components/" + component.source) //console.log("Error loading component:", electricComponent.errorString()) components[index] = electricComponent.createObject( items.playArea, { "index": index, "posX": x, "posY": y, "imgSrc": component.imageName, "toolTipTxt": component.toolTipTxt, "imgWidth": component.imageWidth * currentZoom, "imgHeight": component.imageHeight * currentZoom, "destructible": true }); toolDeleteSticky = false deselect() componentSelected(index) updateComponent(index) } /* Creates wire between two terminals. Condition for creation of wire is that an input terminal * can only be connected to 1 wire, output terminals can be connected by any number of wires, and * an input terminal can be connected with an output terminal only. 'connected' variable is used * to make sure that an input is connected by only 1 wire. */ function terminalPointSelected(terminal) { if(selectedTerminal == -1 || selectedTerminal == terminal) selectedTerminal = terminal else if((selectedTerminal.type != terminal.type) && (selectedTerminal.parent != terminal.parent)) { var inTerminal = terminal.type == "In" ? terminal : selectedTerminal var outTerminal = terminal.type == "Out" ? terminal : selectedTerminal if(connected[inTerminal] == undefined || connected[inTerminal] == -1) { createWire(inTerminal, outTerminal, true) } deselect() } else { deselect() selectedTerminal = terminal terminal.selected = true } } function createWire(inTerminal, outTerminal, destructible) { var wireComponent = Qt.createComponent("qrc:/gcompris/src/activities/digital_electricity/Wire.qml") var wire = wireComponent.createObject( items.playArea, { "from": outTerminal, "to": inTerminal, "destructible": destructible }); inTerminal.value = outTerminal.value inTerminal.wires.push(wire) outTerminal.wires.push(wire) updateWires(inTerminal.parent.index) updateWires(outTerminal.parent.index) updateComponent(inTerminal.parent.index) connected[inTerminal] = outTerminal } /* Updates the output of the component. 'wireVisited' is used to update the value of * each wire once which will avoid updating the outputs of components in an infinite loop. */ function updateComponent(index) { var wireVisited = [] components[index].updateOutput(wireVisited) } /* Updates the orientation of the wire. It is called whenever a new wire is created or * an object is rotated. */ function updateWires(index) { var component = components[index] if(component == undefined || component.noOfInputs == undefined || component.noOfOutputs == undefined) return var rotatedAngle = component.initialAngle * Math.PI / 180 for(var i = 0 ; i < component.noOfInputs ; ++i) { var terminal = component.inputTerminals.itemAt(i) if(terminal.wires.length != 0) { var wire = terminal.wires[0] var otherAngle = wire.from.parent.initialAngle * Math.PI / 180 var x = wire.from.xCenterFromComponent var y = wire.from.yCenterFromComponent var x1 = wire.from.xCenter - x + x * Math.cos(otherAngle) - y * Math.sin(otherAngle) var y1 = wire.from.yCenter - y + x * Math.sin(otherAngle) + y * Math.cos(otherAngle) x = terminal.xCenterFromComponent y = terminal.yCenterFromComponent var x2 = terminal.xCenter - x + x * Math.cos(rotatedAngle) - y * Math.sin(rotatedAngle) var y2 = terminal.yCenter - y + x * Math.sin(rotatedAngle) + y * Math.cos(rotatedAngle) var width = Math.pow((Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)),0.5) + 2 var angle = (180/Math.PI)*Math.atan((y2-y1)/(x2-x1)) if(x2 - x1 < 0) angle = angle - 180 wire.x = x1 wire.y = y1 - wire.height / 2 wire.width = width wire.rotation = angle } } for(var i = 0 ; i < component.noOfOutputs ; ++i) { var terminal = component.outputTerminals.itemAt(i) for(var j = 0 ; j < terminal.wires.length ; ++j) { var x = terminal.xCenterFromComponent var y = terminal.yCenterFromComponent var x1 = terminal.xCenter - x + x * Math.cos(rotatedAngle) - y * Math.sin(rotatedAngle) var y1 = terminal.yCenter - y + x * Math.sin(rotatedAngle) + y * Math.cos(rotatedAngle) var wire = terminal.wires[j] var otherAngle = wire.to.parent.initialAngle * Math.PI / 180 x = wire.to.xCenterFromComponent y = wire.to.yCenterFromComponent var x2 = wire.to.xCenter - x + x * Math.cos(otherAngle) - y * Math.sin(otherAngle) var y2 = wire.to.yCenter - y + x * Math.sin(otherAngle) + y * Math.cos(otherAngle) var width = Math.pow((Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)),0.5) + 2 var angle = (180/Math.PI)*Math.atan((y2-y1)/(x2-x1)) if(x2 - x1 < 0) angle = angle - 180 wire.x = x1 wire.y = y1 wire.width = width wire.rotation = angle } } } function deselect() { if(toolDeleteSticky == false) { toolDelete = false items.availablePieces.toolDelete.state = "notSelected" } items.availablePieces.rotateLeft.state = "canNotBeSelected" items.availablePieces.rotateRight.state = "canNotBeSelected" items.availablePieces.info.state = "canNotBeSelected" items.infoTxt.visible = false selectedIndex = -1 selectedTerminal = -1 for(var i = 0 ; i < components.length ; ++i) { var component = components[i] for(var j = 0 ; j < component.noOfInputs ; ++j) component.inputTerminals.itemAt(j).selected = false for(var j = 0 ; j < component.noOfOutputs ; ++j) component.outputTerminals.itemAt(j).selected = false } } function removeComponent(index) { var component = components[index] for(var i = 0 ; i < component.noOfInputs ; ++i) { var terminal = component.inputTerminals.itemAt(i) if(terminal.wires.length != 0) // Input Terminal can have only 1 wire removeWire(terminal.wires[0]) } for(var i = 0 ; i < component.noOfOutputs ; ++i) { var terminal = component.outputTerminals.itemAt(i) while (terminal.wires.length != 0) { removeWire(terminal.wires[0]) // Output Terminal can have more than 1 wire } } components[index].destroy() deletedIndex.push(index) deselect() } function removeWire(wire) { var inTerminal = wire.to var outTerminal = wire.from var removeIndex = inTerminal.wires.indexOf(wire) inTerminal.wires.splice(removeIndex, 1) removeIndex = outTerminal.wires.indexOf(wire) outTerminal.wires.splice(removeIndex, 1) connected[wire.to] = -1 inTerminal.value = 0 wire.destroy() updateComponent(inTerminal.parent.index) deselect() } function componentSelected(index) { selectedIndex = index items.availablePieces.rotateLeft.state = "canBeSelected" items.availablePieces.rotateRight.state = "canBeSelected" items.availablePieces.info.state = "canBeSelected" } function rotateLeft() { components[selectedIndex].rotationAngle = -2 components[selectedIndex].rotateComponent.start() } function rotateRight() { components[selectedIndex].rotationAngle = 2 components[selectedIndex].rotateComponent.start() } function displayInfo() { var component = components[selectedIndex] var componentTruthTable = component.truthTable deselect() items.infoTxt.visible = true items.infoTxt.text = component.information if(component.infoImageSrc != undefined) { items.infoImage.imgVisible = true items.infoImage.source = url + component.infoImageSrc } else { items.infoImage.imgVisible = false items.infoImage.source = "" } if(componentTruthTable.length == 0) items.displayTruthTable = false else { items.displayTruthTable = true var truthTable = items.truthTablesModel truthTable.clear() truthTable.rows = componentTruthTable.length truthTable.columns = componentTruthTable[0].length truthTable.inputs = component.noOfInputs truthTable.outputs = component.noOfOutputs for(var i = 0 ; i < componentTruthTable.length ; ++i) for(var j = 0 ; j < componentTruthTable[i].length ; ++j) truthTable.append({'value': componentTruthTable[i][j]}) } } function updateToolTip(toolTipTxt) { items.toolTip.show(toolTipTxt) } diff --git a/src/activities/letter-in-word/letter-in-word.js b/src/activities/letter-in-word/letter-in-word.js index 05f6e2e11..e433c02d1 100644 --- a/src/activities/letter-in-word/letter-in-word.js +++ b/src/activities/letter-in-word/letter-in-word.js @@ -1,237 +1,237 @@ /* GCompris - letter-in-word.js * * Copyright (C) 2014 Holger Kaelberer * 2016 Akshat Tandon * * Authors: * Holger Kaelberer (Qt Quick port of click-on-letter) * Akshat Tandon * * 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.6 as Quick .import GCompris 1.0 as GCompris //for ApplicationInfo .import "qrc:/gcompris/src/core/core.js" as Core .import "qrc:/gcompris/src/activities/lang/lang_api.js" as Lang var url = "qrc:/gcompris/src/activities/letter-in-word/resource/" var resUrl = "qrc:/gcompris/src/activities/braille_fun/resource/" var resUrl2 = "qrc:/gcompris/src/activities/click_on_letter/resource/" var levels; var currentLevel; var maxLevel; var currentSubLevel; var currentLetter; var maxSubLevel; var questions; var words; var items; var dataset = null; var frequency; var incorrectFlag = false; var locale; function start(_items) { Core.checkForVoices(_items.main); items = _items; // register the voices for the locale locale = GCompris.ApplicationInfo.getVoicesLocale(items.locale) GCompris.DownloadManager.updateResource(GCompris.DownloadManager.getVoicesResourceForLocale(locale)) loadDataset(); levels = Lang.getAllLessons(dataset) currentLevel = 0; currentSubLevel = 0; maxLevel = levels.length; initLevel(); } function loadDataset() { var resourceUrl = "qrc:/gcompris/src/activities/lang/resource/" var data = Lang.loadDataset(items.parser, resourceUrl, locale); dataset = data["dataset"]; items.background.englishFallback = data["englishFallback"]; } function stop() { items.animateX.stop() } function shuffleString(s) { var a = s; var n = a.length; for(var i = n-1; i > 0; --i) { var j = Math.floor(Math.random() * (i + 1)); var tmp = a[i]; a[i] = a[j]; a[j] = tmp; } return a.join(""); } function initLevel() { items.bar.level = currentLevel + 1; if (currentSubLevel == 0 && !incorrectFlag) { var level = levels[currentLevel]; words = Lang.getLessonWords(dataset, level); Core.shuffle(words); var limit = Math.min(items.currentMode, words.length); words = words.slice(0, limit); frequency = calculateFrequency(); var tempQuestions = generateQuestions(); maxSubLevel = tempQuestions.length; items.score.numberOfSubLevels = maxSubLevel; items.score.currentSubLevel = 1; questions = shuffleString(tempQuestions); items.wordsModel.clear(); for (var i = 0; i < words.length; i++) { items.wordsModel.append({ "spelling": words[i].translatedTxt, "imgurl": words[i].image, "selected": false, "voice": words[i].voice }); } } else { items.score.currentSubLevel = currentSubLevel + 1; } incorrectFlag = false; for(var i = 0; i < words.length; i++) { items.wordsModel.setProperty(i, "selected", false); } currentLetter = questions[currentSubLevel]; items.question = currentLetter; items.animateX.restart(); if(items.currentLetterCase == Quick.Font.MixedCase) { items.questionItem.font.capitalization = (Math.floor(Math.random() * 2) < 1) ? Quick.Font.AllLowercase : Quick.Font.AllUppercase } else { items.questionItem.font.capitalization = items.currentLetterCase } if (GCompris.ApplicationSettings.isAudioVoicesEnabled && GCompris.DownloadManager.haveLocalResource( GCompris.DownloadManager.getVoicesResourceForLocale(locale))) { items.audioVoices.silence(100) playLetter(currentLetter) } } function calculateFrequency() { var freq = []; //regex pattern to detect whether the character is an english alphabet or some accented latin character var pattern = /[A-Za-z\u00C0-\u017F]/; for(var i = 0; i < words.length; i++) { var currentWord = words[i].translatedTxt; for(var j = 0; j < currentWord.length; j++) { var character = currentWord.charAt(j); //consider the character if and only if it is an alphabet or an accented latin character if(pattern.test(character)) { if(freq[character]) { freq[character]++; } else { freq[character] = 1; } } } } return freq; } function generateQuestions() { var freqArr = []; var ques = []; for(var character in frequency) { freqArr.push([character, frequency[character]]); } freqArr.sort(function(a, b) {return b[1] - a[1]}); var limit = Math.min(10, freqArr.length); for(var i = 0; i < limit; i++) { ques.push(freqArr[i][0]) } return ques; } function playLetter(letter) { items.audioVoices.append(GCompris.ApplicationInfo.getAudioFilePath("voices-$CA/"+locale+"/alphabet/" + Core.getSoundFilenamForChar(letter))) } function nextLevel() { items.audioVoices.clearQueue() if(maxLevel <= ++currentLevel) { currentLevel = 0 } currentSubLevel = 0; initLevel(); } function previousLevel() { items.audioVoices.clearQueue() if(--currentLevel < 0) { currentLevel = maxLevel - 1 } currentSubLevel = 0; initLevel(); } function nextSubLevel() { if( ++currentSubLevel >= maxSubLevel) { currentSubLevel = 0 nextLevel() } initLevel(); } function checkAnswer() { var allCorrectSelected = true var modelEntry; var letterIndex; for(var i = 0; i < words.length; i++) { modelEntry = items.wordsModel.get(i); letterIndex = modelEntry.spelling.indexOf(currentLetter); if(letterIndex != -1 && modelEntry.selected == false) { allCorrectSelected = false; break; } if(letterIndex == -1 && modelEntry.selected == true) { allCorrectSelected = false; break; } } if(allCorrectSelected == true) { items.bonus.good("flower"); } else { - items.bonus.bad("flower"); + items.bonus.bad("flower", items.bonus.checkAnswer); } } function checkWord(index) { var modelEntry = items.wordsModel.get(index); items.wordsModel.setProperty(index, "selected", !modelEntry.selected); return modelEntry.selected; } diff --git a/src/activities/magic-hat-minus/magic-hat.js b/src/activities/magic-hat-minus/magic-hat.js index 57f06c4c6..b0ce7374a 100644 --- a/src/activities/magic-hat-minus/magic-hat.js +++ b/src/activities/magic-hat-minus/magic-hat.js @@ -1,231 +1,231 @@ /* GCompris - Hat.qml * * Copyright (C) 2014 Thibaut ROMAIN * * Authors: * Thibaut ROMAIN * * 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.6 as Quick var url = "qrc:/gcompris/src/activities/magic-hat-minus/resource/" var currentLevel var numberOfLevel = 9 var numberOfUserStars var items; var mode; var magicHat var numberOfStars var nbStarsToAddOrRemove var nbStarsToCount var animationCount function start(items_, mode_) { items = items_ mode = mode_ magicHat = items.hat currentLevel = 0 initLevel() } function stop() { } function initLevel() { items.bar.level = currentLevel + 1 magicHat.state = "NormalPosition" numberOfStars = new Array(0, 0, 0) numberOfUserStars = new Array(0, 0, 0) nbStarsToAddOrRemove = new Array(0, 0, 0) nbStarsToCount = new Array(0, 0, 0) animationCount = 0 if(currentLevel > 0) { items.introductionText.visible = false } else { items.introductionText.visible = true } for(var j=0; j<3; j++) { items.repeatersList[0].itemAt(j).initStars() items.repeatersList[1].itemAt(j).initStars() items.repeatersList[2].itemAt(j).resetStars() } var maxValue = mode === "minus" ? 10 : 9 switch(currentLevel) { case 0: numberOfStars[0] = getRandomInt(2,4) break; case 1: numberOfStars[0] = getRandomInt(2,6) break; case 2: numberOfStars[0] = getRandomInt(2,maxValue) break; case 3: numberOfStars[0] = getRandomInt(2,5) numberOfStars[1] = getRandomInt(2,5) break; case 4: numberOfStars[0] = getRandomInt(2,8) numberOfStars[1] = getRandomInt(2,8) break; case 5: numberOfStars[0] = getRandomInt(2,maxValue) numberOfStars[1] = getRandomInt(2,maxValue) break; case 6: numberOfStars[0] = getRandomInt(2,4) numberOfStars[1] = getRandomInt(2,4) numberOfStars[2] = getRandomInt(2,4) break; case 7: numberOfStars[0] = getRandomInt(2,6) numberOfStars[1] = getRandomInt(2,6) numberOfStars[2] = getRandomInt(2,6) break; case 8: numberOfStars[0] = getRandomInt(2,8) numberOfStars[1] = getRandomInt(2,8) numberOfStars[2] = getRandomInt(2,8) break; case 9: numberOfStars[0] = getRandomInt(2,maxValue) numberOfStars[1] = getRandomInt(2,maxValue) numberOfStars[2] = getRandomInt(2,maxValue) break; } for(var i=0; i<3; i++) { items.repeatersList[0].itemAt(i).nbStarsOn = numberOfStars[i] items.repeatersList[1].itemAt(i).nbStarsOn = 0 items.repeatersList[2].itemAt(i).nbStarsOn = 0 items.repeatersList[2].itemAt(i).authorizeClick = false if(numberOfStars[i] > 0) { items.repeatersList[0].itemAt(i).opacity = 1 items.repeatersList[1].itemAt(i).opacity = 1 items.repeatersList[2].itemAt(i).opacity = 1 if(mode === "minus") nbStarsToAddOrRemove[i] = getRandomInt(1, numberOfStars[i]-1) else nbStarsToAddOrRemove[i] = getRandomInt(1, 10-numberOfStars[i]) } else { items.repeatersList[0].itemAt(i).opacity = 0 items.repeatersList[1].itemAt(i).opacity = 0 items.repeatersList[2].itemAt(i).opacity = 0 } } if(mode === "minus") { for(var i=0; i<3; i++) { nbStarsToCount[i] = numberOfStars[i] - nbStarsToAddOrRemove[i] items.repeatersList[1].itemAt(i).nbStarsOn = 0 } } else { for(var i=0; i<3; i++) { nbStarsToCount[i] = numberOfStars[i]+nbStarsToAddOrRemove[i] items.repeatersList[1].itemAt(i).nbStarsOn = nbStarsToAddOrRemove[i] } } } function userClickedAStar(barIndex,state) { if(state) numberOfUserStars[barIndex]++ else numberOfUserStars[barIndex]-- } function verifyAnswer() { if(numberOfUserStars[0] === nbStarsToCount[0] && numberOfUserStars[1] === nbStarsToCount[1] && numberOfUserStars[2] === nbStarsToCount[2]) { items.bonus.good("flower") } else { - items.bonus.bad("flower") + items.bonus.bad("flower", items.bonus.checkAnswer) } } function nextLevel() { if(numberOfLevel <= ++currentLevel ) { currentLevel = 0 } initLevel(); } function previousLevel() { if(--currentLevel < 0) { currentLevel = numberOfLevel - 1 } initLevel(); } function moveStarsUnderHat() { if(currentLevel == 0) { items.introductionText.visible = false } for(var j=0; j<3; j++) { items.repeatersList[0].itemAt(j).moveStars() } } function moveBackMinusStars() { for(var j=0; j<3; j++) { items.repeatersList[0].itemAt(j). moveBackMinusStars(items.repeatersList[1].itemAt(j), nbStarsToAddOrRemove[j]) } } function movePlusStars() { for(var j=0; j<3; j++) { items.repeatersList[1].itemAt(j).moveStars() } } // Function called everytime the first animation ends function animation1Finished(barGroupIndex) { animationCount++ if(barGroupIndex == 0) { if(animationCount === numberOfStars[0] + numberOfStars[1] + numberOfStars[2]) { animationCount = 0 if(mode === "minus") moveBackMinusStars() else movePlusStars() } } else { animationCount = 0 userGuessNumberState() } } // Function called everytime the second animation ends function animation2Finished() { animationCount++ if(animationCount === nbStarsToAddOrRemove[0] + nbStarsToAddOrRemove[1] + nbStarsToAddOrRemove[2]) { animationCount = 0 userGuessNumberState() } } function userGuessNumberState() { for(var i=0; i<3; i++) { if(numberOfStars[i] + nbStarsToAddOrRemove[i]) items.repeatersList[2].itemAt(i).authorizeClick = true } magicHat.state = "GuessNumber" } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } diff --git a/src/activities/share/Share.qml b/src/activities/share/Share.qml index a6b40af7e..02242a928 100644 --- a/src/activities/share/Share.qml +++ b/src/activities/share/Share.qml @@ -1,442 +1,442 @@ /* GCompris - Share.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.6 import GCompris 1.0 import "../../core" import "share.js" as Activity ActivityBase { id: activity onStart: focus = true onStop: {} pageComponent: Rectangle { id: background anchors.fill: parent color: "#abcdef" signal start signal stop Component.onCompleted: { dialogActivityConfig.getInitialConfiguration() activity.start.connect(start) activity.stop.connect(stop) } // Add here the QML items you need to access in javascript QtObject { id: items property Item main: activity.main property alias background: background property alias bar: bar property alias bonus: bonus property alias instruction: instruction property int currentSubLevel: 0 property int nbSubLevel property alias listModel: listModel property bool acceptCandy: false property alias dataset: dataset property alias girlWidget: girlWidget property alias boyWidget: boyWidget property alias candyWidget: candyWidget property alias basketWidget: basketWidget property alias leftWidget: leftWidget property int totalBoys property int totalGirls property int totalCandies property int totalChildren: totalBoys + totalGirls property int barHeightAddon: ApplicationSettings.isBarHidden ? 1 : 3 property int cellSize: Math.round(Math.min(background.width / 12, background.height / (11 + barHeightAddon))) property alias repeaterDropAreas: repeaterDropAreas property int maxNumberOfCandiesPerWidget: 8 } Loader { id: dataset asynchronous: false } onStart: { Activity.start(items) } onStop: { Activity.stop() } property bool vert: background.width >= background.height property int currentBoys: 0 property int currentGirls: 0 property int currentCandies: 0 property int rest property int placedInGirls property int placedInBoys property bool showCount: true property bool easyMode: true property alias wrongMove: wrongMove property bool finished: false //returns true if the x and y is in the "dest" area function contains(x, y, dest) { return (x > dest.x && x < dest.x + dest.width && y > dest.y && y < dest.y + dest.height) } //stop the candy rotation function resetCandy() { items.acceptCandy = false; candyWidget.element.rotation = 0 } //check if the answer is correct function check() { background.resetCandy() background.finished = true var ok = 0 var okRest = 0 if (listModel.count >= items.totalChildren) { for (var i = 0 ; i < listModel.count ; i++) { if (listModel.get(i).nameS === "basket") okRest = listModel.get(i).countS else if (listModel.get(i).countS === Math.floor(items.totalCandies/items.totalChildren)) ok ++ } //condition without rest if (rest == 0 && ok == items.totalChildren) { bonus.good("flower") return } //condition with rest else if (rest == okRest && ok == items.totalChildren) { bonus.good("tux") return } } //else => bad - bonus.bad("flower") + bonus.bad("flower", bonus.checkAnswer) } //center zone Rectangle { id: grid z: 4 //map the coordinates from widgets to grid property var boy: leftWidget.mapFromItem(boyWidget, boyWidget.element.x, boyWidget.element.y) property var girl: leftWidget.mapFromItem(girlWidget, girlWidget.element.x, girlWidget.element.y) property var basket: leftWidget.mapFromItem(basketWidget, basketWidget.element.x, basketWidget.element.y) //show that the widget can be dropped here color: background.contains(boy.x, boy.y, grid) || background.contains(girl.x, girl.y, grid) || background.contains(basket.x, basket.y, grid) ? "#d5e6f7" : "transparent" anchors { top: background.vert ? parent.top : leftWidget.bottom left: background.vert ? leftWidget.right : parent.left topMargin: 20 leftMargin: 20 } width: background.vert ? background.width - leftWidget.width - 40 : background.width - 40 height: ApplicationSettings.isBarHidden ? background.height : background.vert ? background.height - (bar.height * 1.1) : background.height - (bar.height * 1.1) - leftWidget.height //shows/hides the Instruction MouseArea { anchors.fill: parent // first hide the wrong move if visible, then show/hide instruction onClicked: wrongMove.visible ? wrongMove.visible = false : (instruction.opacity === 0) ? instruction.show() : instruction.hide() } ListModel { id: listModel } Flow { id: dropAreas spacing: 10 width: parent.width height: parent.height Repeater { id: repeaterDropAreas model: listModel DropChild { id: rect2 //"nameS" from listModel name: nameS } } } } //instruction rectangle Rectangle { id: instruction anchors.fill: instructionTxt opacity: 0.8 radius: 10 border.width: 2 z: 10 border.color: "#DDD" color: "#373737" property alias text: instructionTxt.text Behavior on opacity { PropertyAnimation { duration: 200 } } //shows/hides the Instruction MouseArea { anchors.fill: parent onClicked: instruction.hide() enabled: instruction.opacity !== 0 } function show() { if(text) opacity = 1 } function hide() { opacity = 0 } } //instruction for playing the game GCText { id: instructionTxt anchors { top: background.vert ? parent.top : leftWidget.bottom topMargin: -10 horizontalCenter: grid.horizontalCenter } opacity: instruction.opacity z: instruction.z fontSize: background.vert ? regularSize : smallSize color: "white" horizontalAlignment: Text.AlignHCenter width: Math.max(Math.min(parent.width * 0.8, text.length * 8), parent.width * 0.3) wrapMode: TextEdit.WordWrap } //left widget, with girl/boy/candy/basket widgets in a grid Rectangle { id: leftWidget width: background.vert ? items.cellSize * 1.74 : background.width height: background.vert ? background.height : items.cellSize * 1.74 color: "#5a9de0" border.color: "#3f81c4" border.width: 4 z: 4 //grid with ok button and images of a boy, a girl, a candy, a basket and the button to display the instructions Grid { id: view x: 10 y: 10 width: background.vert ? leftWidget.width : 3 * bar.height height: background.vert ? background.height - 2 * bar.height : bar.height spacing: 10 columns: background.vert ? 1 : 6 //ok button Image { id: okButton source:"qrc:/gcompris/src/core/resource/bar_ok.svg" sourceSize.width: items.cellSize * 1.5 - view.x / 2 fillMode: Image.PreserveAspectFit MouseArea { id: mouseArea anchors.fill: parent enabled: background.finished ? false : true onPressed: okButton.opacity = 0.6 onReleased: okButton.opacity = 1 onClicked: background.check() } } ChildWidget { id: girlWidget name: "girl" total: items.totalGirls current: background.currentGirls placedInChild: background.placedInGirls } ChildWidget { id: boyWidget name: "boy" total: items.totalBoys current: background.currentBoys placedInChild: background.placedInBoys } BasketWidget { id: basketWidget } CandyWidget { id: candyWidget total: background.easyMode ? items.totalCandies : 8 * items.totalChildren + 1 current: background.currentCandies element.opacity: background.easyMode ? 1 : 0 } Image { id: showInstruction source:"qrc:/gcompris/src/core/resource/bar_hint.svg" sourceSize.width: items.cellSize * 1.5 - view.x / 2 fillMode: Image.PreserveAspectFit MouseArea { anchors.fill: parent enabled: background.finished ? false : true onPressed: showInstruction.opacity = 0.6 onReleased: showInstruction.opacity = 1 onClicked: items.instruction.opacity == 0 ? items.instruction.show() : items.instruction.hide() } } } } // show message warning for placing too many candies in one area Rectangle { id: wrongMove z: 5 color: "orange" radius: width / height * 10 visible: false width: grid.width height: grid.height / 3 anchors.centerIn: grid MouseArea { anchors.fill: parent onClicked: parent.visible = false } GCText { id: wrongMoveText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter width: parent.width - 2 // -2 for margin height: parent.height fontSizeMode: Text.Fit wrapMode: Text.WordWrap color: "#404040" text: qsTr("You can't put more than %1 pieces of candy in the same rectangle").arg(items.maxNumberOfCandiesPerWidget) } } DialogActivityConfig { id: dialogActivityConfig currentActivity: activity content: Component { Item { height: column.height Column { id: column spacing: 10 width: parent.width GCDialogCheckBox { id: easyModeBox width: dialogActivityConfig.width text: qsTr("Display candy counter") checked: background.easyMode onCheckedChanged: { background.easyMode = checked Activity.reloadRandom() } } } } } onLoadData: { if(dataToSave && dataToSave["mode"]) { background.easyMode = (dataToSave["mode"] === "true"); } } onSaveData: { dataToSave = { "mode": "" + background.easyMode } } onClose: home() } //bar buttons DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | level | reload | config} onHelpClicked: { displayDialog(dialogHelp) } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() onReloadClicked: Activity.reloadRandom() onConfigClicked: { dialogActivityConfig.active = true displayDialog(dialogActivityConfig) } } Bonus { id: bonus Component.onCompleted: { win.connect(Activity.nextSubLevel) } onStop: background.finished = false } Score { anchors { left: undefined right: leftWidget.right bottom: background.vert ? bar.top : leftWidget.bottom margins: 3 * ApplicationInfo.ratio } width: girlWidget.width height: background.vert ? (girlWidget.height * 0.8) : girlWidget.height numberOfSubLevels: items.nbSubLevel currentSubLevel: items.currentSubLevel + 1 } } }