Warning, /education/gcompris/src/activities/solar_system/QuizScreen.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - QuizScreen.qml
0002 *
0003 * SPDX-FileCopyrightText: 2018 Aman Kumar Gupta <gupta2140@gmail.com>
0004 *
0005 * Authors:
0006 * Aman Kumar Gupta <gupta2140@gmail.com>
0007 *
0008 * SPDX-License-Identifier: GPL-3.0-or-later
0009 */
0010 import QtQuick 2.12
0011 import GCompris 1.0
0012 import QtGraphicalEffects 1.0
0013 import QtQuick.Controls 2.12
0014
0015 import "../../core"
0016 import "solar_system.js" as Activity
0017
0018 Item {
0019 id: mainQuizScreen
0020 width: parent.width
0021 height: parent.height
0022
0023 property alias score: score
0024 property alias optionListModel: optionListModel
0025 property alias optionListView: optionListView
0026 property alias restartAssessmentMessage: restartAssessmentMessage
0027 property alias blockAnswerButtons: optionListView.blockAnswerButtons
0028 property alias closenessMeter: closenessMeter
0029 property string planetRealImage
0030 property string question
0031 property string closenessMeterValue
0032 property int numberOfCorrectAnswers: 0
0033
0034 Rectangle {
0035 id: questionArea
0036 anchors.right: score.left
0037 anchors.top: parent.top
0038 anchors.left: parent.left
0039 anchors.margins: 10 * ApplicationInfo.ratio
0040 height: questionText.height + 10 * ApplicationInfo.ratio
0041 color: 'white'
0042 radius: 10
0043 border.width: 3
0044 opacity: 0.8
0045 border.color: "black"
0046 GCText {
0047 id: questionText
0048 horizontalAlignment: Text.AlignHCenter
0049 verticalAlignment: Text.AlignVCenter
0050 anchors.centerIn: parent.Center
0051 color: "black"
0052 width: parent.width
0053 wrapMode: Text.Wrap
0054 text: mainQuizScreen.question
0055 }
0056 }
0057
0058 // Model of options for a question
0059 ListModel {
0060 id: optionListModel
0061 }
0062
0063 // This grid has image of the planet in its first column/row (row in case of vertical screen) and the options on the 2nd column/row
0064 Grid {
0065 id: imageAndOptionGrid
0066 columns: (background.horizontalLayout && !items.assessmentMode && items.currentLevel != 1) ? 2 : 1
0067 spacing: 10 * ApplicationInfo.ratio
0068 anchors.top: (questionArea.y + questionArea.height) > (score.y + score.height) ? questionArea.bottom : score.bottom
0069 anchors.left: parent.left
0070 anchors.right: parent.right
0071
0072 // An item to hold image of the planet
0073 Item {
0074 width: background.horizontalLayout ? background.width * 0.40
0075 : background.width - imageAndOptionGrid.anchors.margins * 2
0076 height: background.horizontalLayout ? background.height - bar.height - questionArea.height - 10 * ApplicationInfo.ratio
0077 : (background.height - bar.height - questionArea.height - 10 * ApplicationInfo.ratio) * 0.37
0078
0079 visible: !items.assessmentMode && (items.currentLevel != 1)
0080
0081 Image {
0082 id: planetImageMain
0083 sourceSize.width: Math.min(parent.width, parent.height) * 0.9
0084 anchors.centerIn: parent
0085 source: mainQuizScreen.planetRealImage
0086 fillMode: Image.PreserveAspectCrop
0087 }
0088 }
0089
0090 // An item to hold the list view of options
0091 Item {
0092 width: ( items.assessmentMode || items.currentLevel == 1 ) ? mainQuizScreen.width
0093 : background.horizontalLayout ? background.width * 0.55
0094 : background.width - imageAndOptionGrid.anchors.margins * 2
0095 height: background.horizontalLayout ? itemHeightHorizontal
0096 : itemHeightVertical
0097
0098 readonly property real itemHeightHorizontal: background.height - bar.height - closenessMeter.height - questionArea.height - 10 * ApplicationInfo.ratio
0099 readonly property real itemHeightVertical: (items.bcurrentLevel != 1 && !items.assessmentMode) ? itemHeightHorizontal * 0.39
0100 : itemHeightHorizontal * 0.8
0101
0102 ListView {
0103 id: optionListView
0104 anchors.verticalCenter: parent.verticalCenter
0105 anchors.horizontalCenter: parent.horizontalCenter
0106 width: background.horizontalLayout ? background.width * 0.40
0107 : background.width - imageAndOptionGrid.anchors.margins * 2
0108 height: background.horizontalLayout ? background.height - bar.height - closenessMeter.height * 1.5 - questionArea.height - 50 * ApplicationInfo.ratio
0109 : parent.itemHeightVertical
0110 spacing: background.horizontalLayout ? 10 * ApplicationInfo.ratio : 7.5 * ApplicationInfo.ratio
0111 orientation: Qt.Vertical
0112 verticalLayoutDirection: ListView.TopToBottom
0113 interactive: false
0114 model: optionListModel
0115 currentIndex: -1
0116
0117 readonly property real buttonHeight: (height - 3 * spacing) / 4
0118
0119 add: Transition {
0120 NumberAnimation { properties: "y"; from: parent.y; duration: 500 }
0121 onRunningChanged: {
0122 optionListView.blockAnswerButtons = running
0123 }
0124 }
0125
0126 property bool blockAnswerButtons: false
0127
0128 highlight: Rectangle {
0129 scale: 1.2
0130 color: "#2881C3"
0131 visible: background.keyboardMode
0132 radius: 10 * ApplicationInfo.ratio
0133 Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
0134 Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } }
0135 }
0136
0137 delegate: AnswerButton {
0138 id: optionButton
0139 width: optionListView.width
0140 height: optionListView.buttonHeight
0141 textLabel: optionValue
0142 blockAllButtonClicks: optionListView.blockAnswerButtons
0143 audioEffects: activity.audioEffects
0144
0145 isCorrectAnswer: closeness === 100
0146
0147 onPressed: optionListView.blockAnswerButtons = true
0148 onIncorrectlyPressed: {
0149 if(!items.assessmentMode) {
0150 closenessMeter.stopAnimations()
0151 closenessMeterIncorrectAnswerAnimation.start()
0152 mainQuizScreen.closenessMeterValue = closeness
0153 }
0154 else {
0155 optionListView.blockAnswerButtons = false
0156 Activity.appendAndAddQuestion()
0157 }
0158 }
0159 onCorrectlyPressed: {
0160 if(!items.assessmentMode) {
0161 closenessMeter.stopAnimations()
0162 Activity.currentSubLevel++
0163 score.currentSubLevel = Activity.currentSubLevel
0164 score.playWinAnimation()
0165 particles.burst(30)
0166 closenessMeterCorrectAnswerAnimation.start()
0167 mainQuizScreen.closenessMeterValue = closeness
0168 }
0169 else {
0170 Activity.assessmentModeQuestions.shift()
0171 mainQuizScreen.numberOfCorrectAnswers++
0172 Activity.nextSubLevel(true)
0173 }
0174 }
0175 }
0176 }
0177 }
0178 }
0179
0180 Rectangle {
0181 id: closenessMeter
0182 x: ((background.width - items.bar.barZoom * items.bar.fullButton * 5.6) < (width + 10 * ApplicationInfo.ratio) && background.horizontalLayout) ? background.width - width - 42 * ApplicationInfo.ratio : background.width - width - 10 * ApplicationInfo.ratio
0183 y: (background.width - items.bar.barZoom * items.bar.fullButton * 5.6) < (width + 10 * ApplicationInfo.ratio) ? background.height - bar.height - height - 10 * ApplicationInfo.ratio : background.height - height - 10 * ApplicationInfo.ratio
0184 height: 40 * ApplicationInfo.ratio
0185 width: 150 * ApplicationInfo.ratio
0186 radius: width * 0.06
0187 border.width: 2
0188 border.color: "black"
0189 opacity: 0.78
0190 visible: !items.assessmentMode
0191 Item {
0192 width: parent.width - 3 * ApplicationInfo.ratio
0193 height: parent.height
0194 anchors.centerIn: parent
0195
0196 GCText {
0197 id: closenessText
0198 color: "black"
0199 anchors.fill: parent
0200 fontSizeMode: Text.Fit
0201 horizontalAlignment: Text.AlignHCenter
0202 verticalAlignment: Text.AlignVCenter
0203 text: qsTr("Accuracy: %1%").arg(closenessMeterValue)
0204 }
0205 }
0206
0207 SequentialAnimation {
0208 id: closenessMeterIncorrectAnswerAnimation
0209 onStarted: optionListView.blockAnswerButtons = true
0210 NumberAnimation { target: closenessMeter; property: "scale"; to: 1.1; duration: 450 }
0211 NumberAnimation { target: closenessMeter; property: "scale"; to: 1.0; duration: 450 }
0212 onStopped: optionListView.blockAnswerButtons = false
0213 }
0214
0215 SequentialAnimation {
0216 id: closenessMeterCorrectAnswerAnimation
0217 onStarted: optionListView.blockAnswerButtons = true
0218 NumberAnimation { target: closenessMeter; property: "scale"; to: 1.1; duration: 450 }
0219 NumberAnimation { target: closenessMeter; property: "scale"; to: 1.0; duration: 450 }
0220 NumberAnimation { target: closenessMeter; property: "scale"; to: 1.1; duration: 450 }
0221 NumberAnimation { target: closenessMeter; property: "scale"; to: 1.0; duration: 450 }
0222 ScriptAction { script: { Activity.nextSubLevel() } }
0223 }
0224
0225 ParticleSystemStarLoader {
0226 id: particles
0227 clip: false
0228 }
0229
0230 function stopAnimations() {
0231 optionListView.blockAnswerButtons = false
0232 closenessMeterCorrectAnswerAnimation.stop()
0233 closenessMeterIncorrectAnswerAnimation.stop()
0234 }
0235 }
0236
0237 GCProgressBar {
0238 id: progressBar
0239 height: bar.height * 0.35
0240 width: parent.width * 0.35
0241
0242 readonly property real percentage: (mainQuizScreen.numberOfCorrectAnswers / score.numberOfSubLevels) * 100
0243 message: qsTr("%1%").arg(value)
0244
0245 value: Math.round(percentage * 10) / 10
0246 to: 100
0247
0248 visible: items.assessmentMode
0249 y: parent.height - bar.height - height - 10 * ApplicationInfo.ratio
0250 x: parent.width - width * 1.1
0251
0252 Rectangle {
0253 z: -1
0254 radius: 5 * ApplicationInfo.ratio
0255 anchors.centerIn: parent
0256 height: progressBar.height * 1.25
0257 width: parent.width
0258 color: "#80EEEEEE"
0259 }
0260 }
0261
0262 Rectangle {
0263 id: restartAssessmentMessage
0264 width: parent.width
0265 height: parent.height - bar.height * 1.25
0266 anchors.top: parent.top
0267 anchors.margins: 10 * ApplicationInfo.ratio
0268 anchors.horizontalCenter: parent.horizontalCenter
0269 radius: 4 * ApplicationInfo.ratio
0270 visible: items.assessmentMode && items.restartAssessmentMessage
0271 z: 4
0272 GCText {
0273 anchors.fill: parent
0274 horizontalAlignment: Text.AlignHCenter
0275 verticalAlignment: Text.AlignVCenter
0276 wrapMode: Text.WordWrap
0277 fontSizeMode: mediumSize
0278 text: qsTr("Your final score is: <font color=\"#3bb0de\">%1%</font>.<br><br>%2").arg(progressBar.value).arg(progressBar.value <= 90 ? qsTr("You should score above 90% to become a Solar System expert!<br>Retry to test your skills again or train in normal mode to learn more about the Solar System.") : qsTr("Great! You can replay the assessment to test your knowledge on more questions."))
0279 }
0280
0281 // To prevent clicking on options under it
0282 MouseArea {
0283 anchors.fill: parent
0284 }
0285
0286 onVisibleChanged: scaleAnimation.start()
0287
0288 NumberAnimation {
0289 id: scaleAnimation
0290 target: restartAssessmentMessage
0291 properties: "scale"
0292 from: 0
0293 to: 1
0294 duration: 1500
0295 easing.type: Easing.OutBounce
0296 }
0297 }
0298
0299 Score {
0300 id: score
0301 anchors.bottom: undefined
0302 anchors.right: parent.right
0303 anchors.rightMargin: 10 * ApplicationInfo.ratio
0304 anchors.top: parent.top
0305 z: 0
0306 isScoreCounter: items.assessmentMode ? false : true
0307 }
0308 }