diff --git a/src/activities/numeration_weights_integer/Numeration_weights_integer.qml b/src/activities/numeration_weights_integer/Numeration_weights_integer.qml index 376240ab8..02cdf0361 100644 --- a/src/activities/numeration_weights_integer/Numeration_weights_integer.qml +++ b/src/activities/numeration_weights_integer/Numeration_weights_integer.qml @@ -1,648 +1,660 @@ /* GCompris - Share.qml * * Copyright (C) 2019 Emmanuel Charruau * * 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 . */ // TODO: ne valider que si les poids sont dans la bonne case // TODO: ajouter des niveaux pour pouvoir le faire tester par un élève // TODO: fix error when removing a class dragging it // TODO: give new number only when bonus is finished // TODO: remove cellsize // TODO: is it possible to have a vertical mode? If not remove everything related to vertical mode // TODO: remove settings in bar menu import QtQuick 2.6 import GCompris 1.0 import QtQuick.Layouts 1.3 import QtQuick.Controls 1.5 import QtQml.Models 2.1 import "../../core" import "numeration_weights_integer.js" as Activity ActivityBase { id: activity onStart: focus = true onStop: {} pageComponent: Rectangle { id: background anchors.fill: parent color: "#ffffb3" 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 mainZoneArea: mainZoneArea property alias bar: bar property alias bonus: bonus property alias instruction: instruction property alias warningRectangle: warningRectangle property alias dataset: dataset property alias numberClassListModel: numberClassListModel property alias numberClassDragListModel: numberClassDragListModel property alias numberWeightDragListModel: numberWeightDragListModel property alias numberClassTypeModel: numberClassTypeModel property alias leftWidget: leftWidget property alias progressBar: progressBar property alias numberClassDropAreaRepeater: numberClassDropAreaRepeater property alias classNameListView: classNameListView property int barHeightAddon: ApplicationSettings.isBarHidden ? 1 : 3 property int cellSize: Math.min(background.width / 11, background.height / (9 + barHeightAddon)) property var levels: activity.datasetLoader.item.data property alias numberToConvertRectangle: numberToConvertRectangle } Loader { id: dataset asynchronous: false } onStart: { Activity.start(items) } onStop: { Activity.stop() } property bool vert: background.width >= background.height - //mainZone DropArea { id: mainZoneArea 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 anchors { top: background.vert ? background.top : leftWidget.bottom left: background.vert ? leftWidget.right : parent.left leftMargin: 20 } keys: "NumberClassKey" //shows/hides the objective/instruction MouseArea { anchors.fill: mainZoneArea onClicked: instruction.show() } Rectangle { id: mainZoneAreaDropRectangleVisualisation anchors.fill: parent color: "pink" } onDropped: { var className = drag.source.name drag.source.dragEnabled = false Activity.appendClassNameColumn(className, drag.source, false) } Rectangle { id: topBanner height: mainZoneArea.height / 10 width: mainZoneArea.width anchors { left: mainZoneArea.left top: mainZoneArea.top } color: "green" Rectangle { id: numberToConvertRectangle anchors.fill: numberToConvertRectangleTxt color: "blue" opacity: 0.8 property alias text: numberToConvertRectangleTxt.text } //display number to convert GCText { id: numberToConvertRectangleTxt height: parent.height width: parent.width / 3 anchors { left: numberToConvertRectangle.left top: numberToConvertRectangle.top } opacity: numberToConvertRectangle.opacity //z: instruction.z fontSize: background.vert ? regularSize : smallSize color: "white" style: Text.Outline styleColor: "black" horizontalAlignment: Text.AlignHCenter wrapMode: TextEdit.WordWrap } ProgressBar { id: progressBar height: parent.height width: parent.width / 3 property int percentage: 0 maximumValue: 100 visible: true //!items.isTutorialMode anchors { bottom: parent.bottom right: parent.right rightMargin: 40 } GCText { anchors.centerIn: parent fontSize: mediumSize font.bold: true color: "black" //: The following translation represents percentage. text: qsTr("%1%").arg(parent.value) z: 2 } } } //store strings Integer and Decimal to display in numeration table header ListModel { id: numberClassTypeModel } Rectangle { id: numberClassTypeHeader width: mainZoneArea.width height: mainZoneArea.height / 20 anchors.top: topBanner.bottom anchors.left: parent.left anchors.right: parent.right border.color: "blue" border.width: 1 ListView { id: numberClassTypeHeaderListView anchors { fill: parent} model: numberClassTypeModel orientation: ListView.Horizontal delegate: Rectangle { width: numberClassTypeModel.get(index).numberClassTypeHeaderWidth height: numberClassTypeHeader.height border.width: 1 border.color: "black" color: "lightsteelblue" radius: 2 GCText { id: numberClassHeaderCaption anchors.fill: parent anchors.bottom: parent.bottom fontSizeMode: Text.Fit color: "black" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: numberClassTypeModel.get(index).numberClassType visible: numberClassTypeModel.get(index).numberClassTypeHeaderWidth === 0 ? false : true } } } } Rectangle { id: numberClassHeaders width: mainZoneArea.width height: mainZoneArea.height / 10 anchors.top: numberClassTypeHeader.bottom anchors.left: parent.left anchors.right: parent.right border.color: "red" border.width: 1 GCText { id: numberClassHeadersRectangleAdvice height: parent.height width: parent.width anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } opacity: visualModel.count === 0 ? 1 : 0 fontSizeMode: Text.Fit color: "black" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: qsTr("Drag here the class numbers") } ListView { id: classNameListView anchors { fill: parent} model: visualModel orientation: ListView.Horizontal interactive: false cacheBuffer: 50 } DelegateModel { id: visualModel model: numberClassListModel delegate: nnumberClassHeaderElement //Qt.createComponent("NumberClassHeaderElement.qml") //ask johnny for some help there } } Component { // ? what to do when removed element ? TypeError: Cannot read property 'misplaced' of undefined id: nnumberClassHeaderElement MouseArea { id: dragArea property bool held: false width: mainZoneArea.width / numberClassListModel.count height: numberClassHeaders.height drag.target: held ? content : undefined drag.axis: Drag.XAxis onPressed: held = true onReleased: { if ((content.x < leftWidget.width) && held) //? don't understand why I have a content.x = 0 when held is not true, this point needs to be cleared { console.log("index className element",index) numberClassListModel.get(index).element_src.dragEnabled = true numberClassListModel.remove(index,1) Activity.updateIntegerAndDecimalHeaderWidth() } held = false } Rectangle { id: content anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } width: mainZoneArea.width / numberClassListModel.count height: numberClassHeaders.height / 1.5 border.width: 1 //FIXME: when removing an element of NumberClassList model border color is stilll asked border.color: numberClassListModel.get(index).misplaced === true ? "red" : "lightsteelblue" color: dragArea.held ? "lightsteelblue" : "white" Behavior on color { ColorAnimation { duration: 100 } } radius: 2 Drag.active: dragArea.held Drag.source: dragArea Drag.hotSpot.x: width / 2 Drag.hotSpot.y: height / 2 states: State { when: dragArea.held ParentChange { target: content; parent: root } AnchorChanges { target: content anchors { horizontalCenter: undefined; verticalCenter: undefined } } } GCText { id: numberClassHeaderCaption anchors.fill: parent anchors.bottom: parent.bottom fontSizeMode: Text.Fit color: "black" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: numberClassListModel.get(index).name //here there a problem when removing a number class z: 100 } } DropArea { anchors { fill: parent; margins: 10 } onEntered: { console.log("dragArea.DelegateModel.itemsIndex",dragArea.DelegateModel.itemsIndex) console.log("classNameListView.count",classNameListView.count) //move class name columns except the decimal part which stays always on the last position if (dragArea.DelegateModel.itemsIndex < classNameListView.count - 1) { numberClassListModel.move(drag.source.DelegateModel.itemsIndex, dragArea.DelegateModel.itemsIndex,1) } } } } } - RowLayout { id: numberClassDropAreasGridLayout anchors.top: numberClassHeaders.bottom width: parent.width height: parent.height - topBanner.height - numberClassHeaders.height - numberClassTypeHeader.height spacing: 10 Repeater { id: numberClassDropAreaRepeater - model: numberClassListModel + model: numberClassListModel NumberClassDropArea { id: numberClassDropAreaElement //property alias numberWeightDragListModel: activity.background.numberWeightDragListModel //? className: name //name comes from numberClassListModel Layout.fillHeight: true Layout.fillWidth: true Layout.minimumWidth: 50 Layout.preferredWidth: 100 } } } - } + Tutorial { + id: tutorialSection + + tutorialText.anchors.top: undefined + tutorialText.anchors.bottom: tutorialSection.bottom + tutorialText.anchors.margins: tutorialSection.tutorialText.height + tutorialDetails: Activity.tutorialInstructions + useImage: false + + onSkipPressed: { + Activity.initLevel() + tutorialImage.visible = false + } + } + } ListModel { id: numberClassListModel } ListModel { id: numberClassDragListModel } ListModel { id: numberWeightDragListModel } //instruction rectangle Rectangle { id: instruction anchors.fill: instructionTxt opacity: 0.8 radius: 10 border.width: 2 z: 10 border.color: "black" gradient: Gradient { GradientStop { position: 0.0; color: "#000" } GradientStop { position: 0.9; color: "#666" } GradientStop { position: 1.0; color: "#AAA" } } 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 = 0.8 } function hide() { opacity = 0 } } //display level objective GCText { id: instructionTxt anchors { top: background.vert ? parent.top : leftWidget.bottom topMargin: -10 horizontalCenter: background.horizontalCenter } opacity: instruction.opacity z: instruction.z fontSize: background.vert ? regularSize : smallSize color: "white" style: Text.Outline styleColor: "black" horizontalAlignment: Text.AlignHCenter width: Math.max(Math.min(parent.width * 0.8, text.length * 8), parent.width * 0.3) wrapMode: TextEdit.WordWrap } //display level objective GCText { id: warningTxt anchors { horizontalCenter: background.horizontalCenter verticalCenter: background.verticalCenter } opacity: warningRectangle.opacity z: warningRectangle.z + 1 fontSize: regularSize color: "white" style: Text.Outline styleColor: "black" horizontalAlignment: Text.AlignHCenter width: Math.max(Math.min(parent.width * 0.8, text.length * 8), parent.width * 0.3) wrapMode: TextEdit.WordWrap } Rectangle { id: warningRectangle anchors.fill: warningTxt opacity: 0 radius: 10 border.width: 2 z: 10 border.color: "black" gradient: Gradient { GradientStop { position: 0.0; color: "#000" } GradientStop { position: 0.9; color: "#666" } GradientStop { position: 1.0; color: "#AAA" } } property alias text: warningTxt.text Behavior on opacity { PropertyAnimation { duration: 200 } } //shows/hides the Instruction MouseArea { anchors.fill: parent onClicked: warningRectangle.hide() enabled: warningRectangle.opacity !== 0 } function show() { if(text) opacity = 0.8 } function hide() { opacity = 0 } } //dragable weights list (leftwidget) Rectangle { id: leftWidget width: background.vert ? items.cellSize * 1.74 : background.width height: background.vert ? background.height : items.cellSize * 1.74 color: "#FFFF42" border.color: "#FFD85F" border.width: 4 z: 4 //grid with ok button and the different draggable number weights Flickable { id: flickableElement anchors.fill: parent width: background.height height: leftWidget.width //contentHeight: gridView.height contentHeight: gridView.height * 1.8 //? contentWidth: leftWidget.width boundsBehavior: Flickable.DragAndOvershootBounds Grid { id: gridView x: 10 y: 10 width: parent.width height: background.height //width: background.vert ? leftWidget.width : 3 * bar.height // height: background.vert ? background.height - 2 * bar.height : bar.height spacing: 10 columns: background.vert ? 1 : 5 //ok button Image { id: okButton source:"qrc:/gcompris/src/core/resource/bar_ok.svg" sourceSize.width: items.cellSize * 1.5 fillMode: Image.PreserveAspectFit MouseArea { id: mouseArea anchors.fill: parent enabled: background.finished ? false : true onPressed: okButton.opacity = 0.6 onReleased: okButton.opacity = 1 onClicked: { Activity.checkAnswer() } } } // numbers classes drag elements Repeater { model: numberClassDragListModel NumberClassDragElement { id: classDragElement name: model.name color: model.color Drag.keys: model.dragkeys } } // numbers columns weights and numbers weigths drag elements Repeater { model: numberWeightDragListModel NumberWeightDragElement { id: weightComponentDragElement name: model.name imageName: model.imageName Drag.keys: model.dragkeys weightValue: model.weightValue caption: model.caption color: model.color selected: model.selected } } } } } //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 } } } diff --git a/src/activities/numeration_weights_integer/numeration_weights_integer.js b/src/activities/numeration_weights_integer/numeration_weights_integer.js index 04254a222..3d192c8ec 100644 --- a/src/activities/numeration_weights_integer/numeration_weights_integer.js +++ b/src/activities/numeration_weights_integer/numeration_weights_integer.js @@ -1,565 +1,600 @@ /* GCompris - numeration.js * * Copyright (C) 2019 Emmanuel Charruau * * 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 = 0 var numberOfLevel = 0 //? var items var numbersToConvert = [] var originalNumbersToConvert = [] var numbersCorrectlyAnswered = [] var scorePercentage = 0 var scorePourcentageStep = 0 var wrongAnswerAlreadyGiven = false var selectedNumberWeightDragElementIndex = -1 var numberHasADecimalPart = false var fullClassNamesConstantArray = ["Decimal Part","Unit class","Thousand class","Million class","Milliard class"] var classNamesUsedArray var numberClassesObj = { "Decimal Part": { name: qsTr("Decimal Part"), color: "black", dragkeys: "NumberClassKey"}, "Unit class": { name: qsTr("Unit class"), color: "black", dragkeys: "NumberClassKey"}, "Thousand class": { name: qsTr("Thousand class"), color: "black", dragkeys: "NumberClassKey"}, "Million class": { name: qsTr("Million class"), color: "black", dragkeys: "NumberClassKey"}, "Milliard class": { name: qsTr("Milliard class"), color: "black", dragkeys: "NumberClassKey"} } var numberWeightsColumnsArray = ["HundredColumn","TenColumn","UnitColumn"] var numberWeightComponentConstantArray = ["UnitColumn","TenColumn","HundredColumn","Unit","Ten","Hundred","Thousand","TenThousand", "OneHundredThousand","OneMillion","TenMillion","OneHundredMillion", "OneMilliard","TenMilliard","OneHundredMilliard"] var numberWeightDragArray = { "UnitColumn": { name: qsTr("Unit"), caption: "Unit", imageName: "", weightValue: "1", dragkeys: "numberWeightHeaderKey", color: "lightskyblue", selected: false }, "TenColumn": { name: qsTr("Ten"), caption: "Ten", imageName: "", weightValue: "10", dragkeys: "numberWeightHeaderKey", color: "lightskyblue", selected: false }, "HundredColumn": { name: qsTr("Hundred"), caption: "Hundred", imageName: "", weightValue: "100", dragkeys: "numberWeightHeaderKey", color: "lightskyblue", selected: false }, "Unit": { name: qsTr("Unit"), caption: "", imageName: "unit.svg", weightValue: "1", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "Ten": { name: qsTr("Unit"), caption: "", imageName: "ten.svg", weightValue: "10", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "Hundred": { name: qsTr("Unit"), caption: "", imageName: "hundred.svg", weightValue: "100", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "Thousand": { name: qsTr("Unit"), caption: "1000", imageName: "weightCaption.svg", weightValue: "1000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "TenThousand": { name: qsTr("Unit"), caption: "10 000", imageName: "weightCaption.svg", weightValue: "10000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "OneHundredThousand": { name: qsTr("Unit"), caption: "100 000", imageName: "weightCaption.svg", weightValue: "100000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "OneMillion": { name: qsTr("Unit"), caption: "1 000 000", imageName: "weightCaption.svg", weightValue: "1000000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "TenMillion": { name: qsTr("Unit"), caption: "10 000 000", imageName: "weightCaption.svg", weightValue: "10000000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "OneHundredMillion": { name: qsTr("Unit"), caption: "100 000 000", imageName: "weightCaption.svg", weightValue: "100000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false }, "OneMilliard": { name: qsTr("Unit"), caption: "1 000 000 000", imageName: "weightCaption.svg", weightValue: "1000000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false }, "TenMilliard": { name: qsTr("Unit"), caption: "10 000 000 000", imageName: "weightCaption.svg", weightValue: "10000000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false }, "OneHundredMilliard": { name: qsTr("Unit"), caption: "100 000 000 000", imageName: "weightCaption.svg", weightValue: "100000000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false } } // for what is used name in numberWeightDragArray ? //? var numberClassTypeColumnsArray = ["Integer Part","Decimal Part"] +var tutorialInstructions = [ + { + "instruction": qsTr("This activity teaches how to convert decimal numbers to binary numbers."), + "instructionQml" : "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial1.qml" + }, + { + "instruction": qsTr("Computers use transistors to count and transistors have only two states, 0 and 1. Mathematically, these states are represented by 0 and 1, which makes up the binary system of numeration."), + "instructionQml" : "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial2.qml" + }, + { + "instruction": qsTr("In the activity 0 and 1 are simulated by bulbs, switched on or off."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial3.qml" + }, + { + "instruction": qsTr("Binary system uses these numbers very efficiently, allowing to count from 0 to 255 with 8 bits only."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial4.qml" + }, + { + "instruction": qsTr("Each bit adds a progressive value, corresponding to the powers of 2, ascending from right to left: bit 1 → 2⁰=1 , bit 2 → 2¹=2 , bit 3 → 2²=4 , bit 4 → 2³=8 , bit 5 → 2⁴=16 , bit 6 → 2⁵=32 , bit 7 → 2⁶=64 , bit 8 → 2⁷=128."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial5.qml" + }, + { + "instruction": qsTr("To convert a decimal 5 to a binary value, 1 and 4 are added."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial6.qml" + }, + { + "instruction": qsTr("Their corresponding bits are set to 1, the others set to 0. Decimal 5 is equal to binary 101."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial7.qml" + }, + { + "instruction": qsTr("This image will help you to compute bits' value."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial5.qml" + } + ] + function removeClassInNumberClassesArray(className) { console.log(numberClassesArray) var index = numberClassesArray.indexOf(className); if (index > -1) { numberClassesArray.splice(index, 1); } console.log(numberClassesArray) } function removeClassInNumberClassesArray() { numberClassesArray.pop(numberClass) } function setNumberWeightHeader(numberWeightImageTile,imageName,caption,weightValue) { if ( imageName !== "") { numberWeightImageTile.source = "qrc:/gcompris/src/activities/numeration_weights_integer/resource/images/" + imageName } numberWeightImageTile.caption = caption numberWeightImageTile.weightValue = weightValue } function setNumberWeightComponent(numberWeightImageTile,imageName,caption,weightValue) { if ( imageName !== "") { numberWeightImageTile.source = "qrc:/gcompris/src/activities/numeration_weights_integer/resource/images/" + imageName numberWeightImageTile.caption = caption numberWeightImageTile.weightValue = weightValue } } function removeNumberWeightComponent(numberWeightImageTile) { numberWeightImageTile.source = "" numberWeightImageTile.caption = "" numberWeightImageTile.weightValue = "" numberWeightImageTile.border.color = "black" } function resetNumerationTable() { for (var i = 0; i=0; i--,classNamesUsedIndex++) { if (items.numberClassListModel.get(i).name === classNamesUsedArray[classNamesUsedIndex]) { items.numberClassListModel.setProperty(i, "misplaced", false) } else { items.numberClassListModel.setProperty(i, "misplaced", true) allClassesColumnsInRightPositions = false } } return allClassesColumnsInRightPositions } function expectedAndEnteredValuesAreEquals() { var enteredValue = readNumerationTableEnteredValue() console.log("enteredValue/expected value:",enteredValue + " / " + parseInt(numbersToConvert[0],10)) //test if entered value is equal to number expected if (enteredValue === parseInt(numbersToConvert[0],10)) { return true } else { return false } } function checkEnteredValue() { var _expectedAndEnteredValuesAreEquals = expectedAndEnteredValuesAreEquals() if (_expectedAndEnteredValuesAreEquals) { return true } else { return false } } function evaluateAndDisplayProgresses(correctAnswer) { if (correctAnswer) { wrongAnswerAlreadyGiven = false items.bonus.good("flower") console.log("correct: scorePercentage before incrementation",scorePercentage) numbersCorrectlyAnswered.push(numbersToConvert.shift()) //remove first element and copy it in numbersCorrectlyAnswered scorePercentage = scorePercentage + scorePourcentageStep console.log("correct: scorePercentage after incrementation",scorePercentage) items.progressBar.value = scorePercentage if (scorePercentage > 97) { return true } items.numberToConvertRectangle.text = numbersToConvert[0] console.log("original NumbersToConvert: " + originalNumbersToConvert) console.log("NumbersToConvert: " + numbersToConvert) console.log("numbersCorrectlyAnswered: " + numbersCorrectlyAnswered) return } else { items.bonus.bad("flower") items.numberToConvertRectangle.text = numbersToConvert[0] console.log("incorrect: scorePercentage before incrementation",scorePercentage) console.log("wrongAnswerAlreadyGiven: ", wrongAnswerAlreadyGiven) if (wrongAnswerAlreadyGiven === false) { scorePercentage = scorePercentage - scorePourcentageStep if (scorePercentage < 0) scorePercentage = 0 items.progressBar.value = scorePercentage if (numbersToConvert.length < 2) { numbersToConvert.splice(2, 0, numbersCorrectlyAnswered[Math.floor(Math.random() * numbersCorrectlyAnswered.length)]) } console.log("number to convert before splice: ",numbersToConvert) numbersToConvert.splice(2, 0, numbersToConvert[0]); console.log("number to convert after splice: ",numbersToConvert) wrongAnswerAlreadyGiven = true console.log("incorrect: scorePercentage after incrementation",scorePercentage) } console.log("NumbersToConvert length: " + numbersToConvert.length) console.log("original NumbersToConvert: " + originalNumbersToConvert) console.log("NumbersToConvert: " + numbersToConvert) console.log("numbersCorrectlyAnswered: " + numbersCorrectlyAnswered) return false } } function start(items_) { items = items_ currentLevel = 0 setNumberWeightDragListModel(numberWeightComponentConstantArray) initLevel() numberOfLevel = items.levels.length // ? } function setNumberClassTypeListModel() { items.numberClassTypeModel.append({"numberClassType": "Integer Part", "numberClassTypeHeaderWidth": 0}) if (hasNumberADecimalPart()) { addDecimalHeaderToNumberClassTypeModel() } } function setClassNamesUsedArray(fullClassNamesArray) { var smallerNumberClass = items.levels[currentLevel].smallerNumberClass var biggerNumberClass = items.levels[currentLevel].biggerNumberClass if (!isClassNamePresentInfullClassNamesArray(fullClassNamesArray, smallerNumberClass)) { return fullClassNamesConstantArray } if (!isClassNamePresentInfullClassNamesArray(fullClassNamesArray, biggerNumberClass)) { return fullClassNamesConstantArray } return fullClassNamesArray.slice(fullClassNamesArray.indexOf(smallerNumberClass),fullClassNamesArray.indexOf(biggerNumberClass)+1) } function isClassNamePresentInfullClassNamesArray(fullClassNamesArray, className) { if (fullClassNamesArray.indexOf(className) !== -1) { return true } else { items.warningRectangle.text = qsTr("The class name \"" + className + "\" is not present in the available list: \"" + fullClassNamesArray+ "\". Check your configuration file (lower case or uppercase error?).") items.warningRectangle.show() return false } } function hasNumberADecimalPart() { for (var i=0; i + * + * Authors: + * Timothée Giet + * + * 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 "../../../activities" + + +Rectangle { + id: tutorial1 + + Component.onCompleted: { + tutorial1.state === '' ? tutorial1.state = 'other' : tutorial1.state = '' + } + + + + anchors.fill: parent + color: "#80FFFFFF" + + states: [ + // This adds a second state to the container where the rectangle is farther to the right + + State { name: "other" + + PropertyChanges { + target: ActivityBase.activity.background + x: 200 + } + } + ] + transitions: [ + // This adds a transition that defaults to applying to all state changes + + Transition { + + // This applies a default NumberAnimation to any changes a state change makes to x or y properties + NumberAnimation { properties: "x,y" } + } + ] + +} diff --git a/src/activities/numeration_weights_integer/resource/tutorial2.qml b/src/activities/numeration_weights_integer/resource/tutorial2.qml new file mode 100644 index 000000000..740c2d858 --- /dev/null +++ b/src/activities/numeration_weights_integer/resource/tutorial2.qml @@ -0,0 +1,115 @@ +/* GCompris - tutorial2.qml + * + * Copyright (C) 2018 Timothée Giet + * + * Authors: + * Timothée Giet + * + * 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" + +Rectangle { + anchors.fill: parent + color: "#80FFFFFF" + + Item { + width: parent.width + height: parent.height * 0.5 + + Image { + source: "transistor.svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.height: implicitHeight + } + } + + Item { + width: parent.width * 0.2 + height: parent.height * 0.5 + anchors.bottom: parent.bottom + anchors.left: parent.left + + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + text: "0" + font.pixelSize: parent.height * 0.5 + color: "black" + horizontalAlignment: Text.AlignRight + width: 0.9 * parent.width + height: 0.9 * parent.height + z: 2 + } + } + + Item { + width: parent.width * 0.3 + height: parent.height * 0.4 + anchors.bottom: parent.bottom + anchors.right: parent.horizontalCenter + anchors.bottomMargin: parent.height * 0.05 + + Image { + source: "" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + + } + + Item { + width: parent.width * 0.3 + height: parent.height * 0.4 + anchors.bottom: parent.bottom + anchors.left: parent.horizontalCenter + anchors.bottomMargin: parent.height * 0.05 + + Image { + source: "" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + + } + + Item { + width: parent.width * 0.2 + height: parent.height * 0.5 + anchors.bottom: parent.bottom + anchors.right: parent.right + + GCText { + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + text: "1" + font.pixelSize: parent.height * 0.5 + color: "black" + horizontalAlignment: Text.AlignLeft + width: 0.9 * parent.width + height: 0.9 * parent.height + z: 2 + } + } +} diff --git a/src/activities/numeration_weights_integer/resource/tutorial3.qml b/src/activities/numeration_weights_integer/resource/tutorial3.qml new file mode 100644 index 000000000..80792a0e3 --- /dev/null +++ b/src/activities/numeration_weights_integer/resource/tutorial3.qml @@ -0,0 +1,116 @@ +/* GCompris - tutorial3.qml + * + * Copyright (C) 2018 Timothée Giet + * + * Authors: + * Timothée Giet + * + * 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" + +Rectangle { + anchors.fill: parent + color: "#80FFFFFF" + + + Item { + width: parent.width + height: parent.height * 0.5 + + Image { + source: "transistor.svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.height: implicitHeight + } + } + + Item { + width: parent.width * 0.2 + height: parent.height * 0.5 + anchors.bottom: parent.bottom + anchors.left: parent.left + + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + text: "0" + font.pixelSize: parent.height * 0.5 + color: "black" + horizontalAlignment: Text.AlignRight + width: 0.9 * parent.width + height: 0.9 * parent.height + z: 2 + } + } + + Item { + width: parent.width * 0.3 + height: parent.height * 0.4 + anchors.bottom: parent.bottom + anchors.right: parent.horizontalCenter + anchors.bottomMargin: parent.height * 0.05 + + Image { + source: "bulb_off.svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + + } + + Item { + width: parent.width * 0.3 + height: parent.height * 0.4 + anchors.bottom: parent.bottom + anchors.left: parent.horizontalCenter + anchors.bottomMargin: parent.height * 0.05 + + Image { + source: "bulb_on.svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + + } + + Item { + width: parent.width * 0.2 + height: parent.height * 0.5 + anchors.bottom: parent.bottom + anchors.right: parent.right + + GCText { + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + text: "1" + font.pixelSize: parent.height * 0.5 + color: "black" + horizontalAlignment: Text.AlignLeft + width: 0.9 * parent.width + height: 0.9 * parent.height + z: 2 + } + } +} diff --git a/src/activities/numeration_weights_integer/resource/tutorial4.qml b/src/activities/numeration_weights_integer/resource/tutorial4.qml new file mode 100644 index 000000000..669c00177 --- /dev/null +++ b/src/activities/numeration_weights_integer/resource/tutorial4.qml @@ -0,0 +1,142 @@ +/* GCompris - tutorial4.qml + * + * Copyright (C) 2018 Timothée Giet + * + * Authors: + * Timothée Giet + * + * 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" + +Rectangle { + anchors.fill: parent + color: "#80FFFFFF" + + Item { + id: topBlock + width: parent.width + height: parent.height * 0.2 + + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + text: qsTr("0 to 255 with") + fontSizeMode: Text.Fit + minimumPixelSize: 15 + color: "black" + horizontalAlignment: Text.AlignHCenter + width: 0.9 * parent.width + height: 0.9 * parent.height + wrapMode: Text.WordWrap + z: 2 + } + } + + Row { + id: tableBlock1 + width: parent.width * 0.9 + height: parent.height * 0.2 + anchors.top: topBlock.bottom + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + Repeater { + model: ["", "", "", "", "", "", "", ""] + Item { + id: item128 + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + text: modelData + fontSizeMode: Text.Fit + minimumPixelSize: 15 + color: "black" + horizontalAlignment: Text.AlignHCenter + width: 0.9 * parent.width + height: 0.9 * parent.height + wrapMode: Text.WordWrap + z: 2 + } + } + } + } + + Row { + id: bulbBlock + width: parent.width * 0.9 + height: parent.height * 0.4 + anchors.top: tableBlock1.bottom + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + Repeater { + model: ["off", "off", "off", "off", "off", "off", "off", "off"] + Item { + id: item128 + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + Image { + source: "bulb_" + modelData + ".svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + } + } + } + + Row { + width: parent.width * 0.9 + height: parent.height * 0.2 + anchors.top: bulbBlock.bottom + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + Repeater { + model: ["0", "0", "0", "0", "0", "0", "0", "0"] + Item { + id: item128 + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + text: modelData + fontSizeMode: Text.Fit + minimumPixelSize: 15 + color: "black" + horizontalAlignment: Text.AlignHCenter + width: 0.9 * parent.width + height: 0.9 * parent.height + wrapMode: Text.WordWrap + z: 2 + } + } + } + } +} diff --git a/src/activities/numeration_weights_integer/resource/tutorial5.qml b/src/activities/numeration_weights_integer/resource/tutorial5.qml new file mode 100644 index 000000000..72e4069e2 --- /dev/null +++ b/src/activities/numeration_weights_integer/resource/tutorial5.qml @@ -0,0 +1,165 @@ +/* GCompris - tutorial5.qml + * + * Copyright (C) 2018 Timothée Giet + * + * Authors: + * Timothée Giet + * + * 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" + +Rectangle { + anchors.fill: parent + color: "#80FFFFFF" + + Item { + id: topBlock + width: parent.width + height: parent.height * 0.2 + + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + text: qsTr("0 to 255 with") + fontSizeMode: Text.Fit + minimumPixelSize: 15 + color: "black" + horizontalAlignment: Text.AlignHCenter + width: 0.9 * parent.width + height: 0.9 * parent.height + wrapMode: Text.WordWrap + z: 2 + } + } + + Row { + id: tableBlock1 + width: parent.width * 0.9 + height: parent.height * 0.2 + anchors.top: topBlock.bottom + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + Repeater { + model: ["128", "64", "32", "16", "8", "4", "2", "1"] + Item { + id: item128 + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + text: modelData + fontSizeMode: Text.Fit + minimumPixelSize: 15 + color: "black" + horizontalAlignment: Text.AlignHCenter + width: 0.9 * parent.width + height: 0.9 * parent.height + wrapMode: Text.WordWrap + z: 2 + } + } + } + } + + Row { + id: tableBlock2 + width: parent.width * 0.9 + height: parent.height * 0.1 + anchors.verticalCenter: tableBlock1.top + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + tableBlock1.width/20 + Repeater { + model: 7 + Item { + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + Image { + source: "multipleTwo.svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + } + } + } + + Row { + id: bulbBlock + width: parent.width * 0.9 + height: parent.height * 0.4 + anchors.top: tableBlock1.bottom + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + Repeater { + model: ["off", "off", "off", "off", "off", "off", "off", "off"] + Item { + id: item128 + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + Image { + source: "bulb_" + modelData + ".svg" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + sourceSize.width: implicitWidth + } + } + } + } + + Row { + width: parent.width * 0.9 + height: parent.height * 0.2 + anchors.top: bulbBlock.bottom + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.05 + Repeater { + model: ["0", "0", "0", "0", "0", "0", "0", "0"] + Item { + id: item128 + width: parent.width / 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + GCText { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + text: modelData + fontSizeMode: Text.Fit + minimumPixelSize: 15 + color: "black" + horizontalAlignment: Text.AlignHCenter + width: 0.9 * parent.width + height: 0.9 * parent.height + wrapMode: Text.WordWrap + z: 2 + } + } + } + } +} diff --git a/src/core/Tutorial.qml b/src/core/Tutorial.qml index 4499d386e..4301d1a99 100644 --- a/src/core/Tutorial.qml +++ b/src/core/Tutorial.qml @@ -1,193 +1,216 @@ /* GCompris - Tutorial.qml * * Copyright (C) 2017 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 . */ /* * A QML component for tutorial in activity in GCompris. * * Use Tutorial when you want to add a tutorial section which contains instructions and images. * * Contains the following basic layout elements: text (instructions), a Skip, * a Next and a Previous button to leave the tutorial or navigate through it. * The skipPressed, nextPressed, previousPressed signals are emitted when user clicks on skip, next and previous button respectively. * */ /* To use the component add: * Tutorial { * id: tutorialSection * source: "sourceForTutorialBackgroundImage" * tutorialDetails: Activity.tutorialInstructions * onSkipPressed: { * Activity.initLevel() * } * } */ import QtQuick 2.6 import GCompris 1.0 Item { id: tutorialSection anchors.fill: parent /* type: int * Counter for tutorial instructions */ property int tutorialNumber: 0 /* Container for all the tutorial instructions */ property var tutorialDetails /* Do we use image or qml files for illustrations */ property bool useImage: true // Emitted when skipButton is clicked signal skipPressed // Emitted when nextButton is clicked signal nextPressed // Emitted when previousButton is clicked signal previousPressed + property alias tutorialText: tutorialText + // Tutorial instructions GCText { id: tutorialText anchors { horizontalCenter: parent.horizontalCenter top: parent.top topMargin: 10 } text: tutorialDetails ? tutorialDetails[tutorialNumber].instruction : "" fontSizeMode: Text.Fit minimumPixelSize: 10 color: "black" horizontalAlignment: Text.AlignHLeft width: Math.min(implicitWidth, 0.8 * parent.width) height: Math.min(implicitHeight, 0.25 * parent.height) wrapMode: Text.WordWrap z: 2 } MouseArea { anchors.fill: parent } Rectangle { id: tutorialTextContainer anchors.top: tutorialText.top anchors.horizontalCenter: tutorialText.horizontalCenter width: tutorialText.width + 20 height: tutorialText.height + 2 opacity: 0.8 radius: 10 border.width: 6 color: "white" border.color: "#87A6DD" } // previousButton: It emits skipPressed and navigates to previous tutorial when clicked IntroButton { id: previousButton - width: parent.width / 4 + width: parent.width / 5 height: 90 z: 5 anchors.right: nextButton.left anchors.topMargin: 15 anchors.rightMargin: 15 anchors.top: tutorialTextContainer.bottom visible: tutorialNumber != 0 text: qsTr("Previous") onClicked: { --tutorialNumber previousPressed() } } // nextButton: It emits nextPressed which navigates to next tutorial when clicked IntroButton { id: nextButton - width: parent.width / 4 + width: parent.width / 5 height: 90 z: 5 anchors.right: skipButton.left anchors.topMargin: 15 anchors.rightMargin: 15 anchors.top: tutorialTextContainer.bottom visible: tutorialNumber != (tutorialDetails.length - 1) text: qsTr("Next") onClicked: { ++tutorialNumber nextPressed() } } // skipButton: It emits the skipPressed signal which calls the initLevel to close the tutorial when clicked. IntroButton { id: skipButton - width: parent.width / 4 + width: parent.width / 5 height: 90 z: 5 anchors.right: parent.right anchors.rightMargin: 15 anchors.topMargin: 15 anchors.top: tutorialTextContainer.bottom text: nextButton.visible ? qsTr("Skip") : qsTr("Start") onClicked: { tutorialSection.visible = false skipPressed() } } + IntroButton { + id: showButton + width: parent.width / 5 + height: 90 + z: 5 + anchors.right: previousButton.visible ? previousButton.left : nextButton.left + anchors.topMargin: 15 + anchors.rightMargin: 15 + anchors.top: tutorialTextContainer.bottom + visible: tutorialNumber != (tutorialDetails.length - 1) + + text: qsTr("Show") + + onClicked: { + ++tutorialNumber + nextPressed() + } + } + + + // Image component for tutorial instructions Image { id: tutorialImage visible: useImage width: parent.width * 0.8 height: (parent.height - nextButton.height) * 0.48 fillMode: Image.PreserveAspectFit source: tutorialDetails && useImage ? tutorialDetails[tutorialNumber].instructionImage : "" anchors { top: previousButton.bottom topMargin: 10 horizontalCenter: parent.horizontalCenter } } // Alternative QML component for tutorial instructions Loader { id: tutorialQml enabled: !tutorialImage.visible width: parent.width * 0.8 height: (parent.height - nextButton.height) * 0.48 source: tutorialDetails && !useImage ? tutorialDetails[tutorialNumber].instructionQml : "" anchors { top: previousButton.bottom topMargin: 10 horizontalCenter: parent.horizontalCenter } } }