Warning, /education/gcompris/src/activities/renewable_energy/RenewableEnergy.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - renewable_energy.qml 0002 * 0003 * SPDX-FileCopyrightText: 2015 Sagar Chand Agarwal <atomsagar@gmail.com> 0004 * SPDX-FileCopyrightText: 2022 Timothée Giet <animtim@gmail.com> 0005 * 0006 * Authors: 0007 * Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version) 0008 * Sagar Chand Agarwal <atomsagar@gmail.com> (Qt Quick port) 0009 * Timothée Giet <animtim@gmail.com> (Big refactoring) 0010 * 0011 * SPDX-License-Identifier: GPL-3.0-or-later 0012 */ 0013 import QtQuick 2.12 0014 import GCompris 1.0 0015 import "../../core" 0016 import "qrc:/gcompris/src/core/core.js" as Core 0017 0018 ActivityBase { 0019 id: activity 0020 0021 onStart: focus = true 0022 onStop: {} 0023 0024 property string url: "qrc:/gcompris/src/activities/renewable_energy/resource/" 0025 property string url2: "qrc:/gcompris/src/activities/watercycle/resource/" 0026 0027 pageComponent: Image { 0028 id: background 0029 anchors.fill: parent 0030 source: "qrc:/gcompris/src/activities/chess/resource/background-wood.svg" 0031 sourceSize.width: width 0032 sourceSize.height: height 0033 0034 signal start 0035 signal stop 0036 0037 Component.onCompleted: { 0038 activity.start.connect(start) 0039 activity.stop.connect(stop) 0040 } 0041 0042 // Add here the QML items you need to access in javascript 0043 0044 QtObject { 0045 id: items 0046 property Item main: activity.main 0047 property alias background: background 0048 property bool isVertical: background.width < background.height - bar.height * 1.2 0049 property alias bonus: bonus 0050 property GCSfx audioEffects: activity.audioEffects 0051 // we initialize it to -1, so onStart it forces a layout refresh when it's set to 0 0052 property int currentLevel: -1 0053 property int numberOfLevel: 3 0054 property bool sunIsUp: true 0055 property color consumeColor: "#E09C4C" 0056 property color consumeColorBorder: "#81531E" 0057 property color produceColor: "#E9E87F" 0058 property color produceColorBorder: "#82811E" 0059 property bool hasWon: false 0060 0061 onSunIsUpChanged: { 0062 if(sunIsUp) 0063 sun.state = "sunUp" 0064 else 0065 sun.state = "sunDown" 0066 } 0067 } 0068 0069 onStart: items.currentLevel = Core.getInitialLevel(items.numberOfLevel); 0070 onStop: { 0071 hydro.item.stopTimer(); 0072 if(wind.item) 0073 wind.item.stopTimer(); 0074 } 0075 0076 function initLevel() { 0077 if(message.visible) 0078 return; 0079 residentSmallSwitch.on = false 0080 residentBigSwitch.on = false 0081 tuxSwitch.on = false 0082 stepDown.started = false 0083 hydro.item.stop() 0084 if(wind.item) 0085 wind.item.stop() 0086 if(solar.item) 0087 solar.item.stop() 0088 } 0089 0090 function nextLevel() { 0091 if(items.numberOfLevel <= ++items.currentLevel) { 0092 // Stay on the last level 0093 items.currentLevel = items.numberOfLevel - 1 0094 } 0095 } 0096 0097 function previousLevel() { 0098 items.currentLevel = Core.getPreviousLevel(items.currentLevel, items.numberOfLevel); 0099 } 0100 0101 function checkForNextLevel() { 0102 switch(items.currentLevel) { 0103 case 0: 0104 if(tuxSwitch.on) 0105 win() 0106 break 0107 case 1: 0108 if(tuxSwitch.on && residentSmallSwitch.on) 0109 win() 0110 break 0111 case 2: 0112 if(!items.hasWon && 0113 tuxSwitch.on && residentSmallSwitch.on && residentBigSwitch.on) { 0114 items.hasWon = true 0115 win() 0116 } 0117 break 0118 } 0119 } 0120 0121 Item { 0122 id: layoutArea 0123 width: parent.height - bar.height * 1.2 0124 height: width 0125 anchors.horizontalCenter: background.horizontalCenter 0126 states: [ 0127 State { 0128 name: "verticalLayout" 0129 when: items.isVertical 0130 PropertyChanges { 0131 target: layoutArea 0132 width: parent.width 0133 anchors.bottomMargin: bar.height * 0.2 0134 } 0135 AnchorChanges { 0136 target: layoutArea 0137 anchors.top: undefined 0138 anchors.bottom: bar.top 0139 } 0140 }, 0141 State { 0142 name: "horizontalLayout" 0143 when: !items.isVertical 0144 PropertyChanges { 0145 target: layoutArea 0146 width: parent.height - bar.height * 1.2 0147 anchors.bottomMargin: 0 0148 } 0149 AnchorChanges { 0150 target: layoutArea 0151 anchors.top: parent.top 0152 anchors.bottom: undefined 0153 } 0154 } 0155 ] 0156 } 0157 0158 Image { 0159 id: sky 0160 anchors.top: layoutArea.top 0161 anchors.left: layoutArea.left 0162 width: layoutArea.width 0163 height: layoutArea.height * 0.305 0164 sourceSize.width: width 0165 sourceSize.height: height 0166 source: activity.url2 + "sky.svg" 0167 visible: true 0168 } 0169 0170 Image { 0171 id: sun 0172 source: activity.url2 + "sun.svg" 0173 width: layoutArea.width * 0.1 0174 fillMode: Image.PreserveAspectFit 0175 sourceSize.width: width 0176 anchors { 0177 left: layoutArea.left 0178 top: layoutArea.top 0179 leftMargin: layoutArea.width * 0.056 0180 topMargin: layoutArea.height * 0.256 0181 } 0182 0183 MouseArea { 0184 id: sun_area 0185 anchors.fill: sun 0186 onClicked: { 0187 if(hydro.item.cloudOpacity == 0) 0188 items.sunIsUp = true; 0189 } 0190 } 0191 state: "sunUp" 0192 states: [ 0193 State { 0194 name: "sunDown" 0195 PropertyChanges { 0196 target: sun 0197 anchors.topMargin: layoutArea.height * 0.256 0198 } 0199 }, 0200 State { 0201 name: "sunUp" 0202 PropertyChanges { 0203 target: sun 0204 anchors.topMargin: layoutArea.height * 0.056 0205 } 0206 } 0207 ] 0208 0209 transitions: [ 0210 Transition { 0211 from: "sunUp"; to: "sunDown"; 0212 NumberAnimation { property: "anchors.topMargin"; easing.type: Easing.InOutQuad; duration: 5000 } 0213 }, 0214 Transition { 0215 from: "sunDown"; to: "sunUp"; 0216 ScriptAction { script: { 0217 items.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/bleep.wav'); 0218 hydro.item.vaporAnimLoop = true; 0219 hydro.item.vaporIsUp = true; 0220 hydro.item.cloudIsUp = true; 0221 } 0222 } 0223 NumberAnimation { property: "anchors.topMargin"; easing.type: Easing.InOutQuad; duration: 5000 } 0224 } 0225 ] 0226 } 0227 0228 Image { 0229 id: sea 0230 anchors.left: layoutArea.left 0231 anchors.bottom: layoutArea.bottom 0232 width: layoutArea.width 0233 height: layoutArea.height * 0.7 0234 sourceSize.width: width 0235 sourceSize.height: height 0236 source: activity.url2 + "sea.svg" 0237 } 0238 0239 Image { 0240 id: landscape 0241 anchors.fill: layoutArea 0242 sourceSize.width: width 0243 sourceSize.height: height 0244 source: activity.url2 + "landscape.svg" 0245 } 0246 0247 Loader { 0248 id: wind 0249 anchors.fill: layoutArea 0250 source: items.currentLevel > 0 ? "Wind.qml" : "" 0251 } 0252 0253 Loader { 0254 id: solar 0255 anchors.fill: layoutArea 0256 source: items.currentLevel > 1 ? "Solar.qml" : "" 0257 } 0258 0259 Loader { 0260 id: hydro 0261 anchors.fill: layoutArea 0262 source: "Hydro.qml" 0263 } 0264 0265 IntroMessage { 0266 id: message 0267 z: 100 0268 anchors { 0269 top: parent.top 0270 topMargin: 10 0271 right: parent.right 0272 rightMargin: 5 0273 left: parent.left 0274 leftMargin: 5 0275 } 0276 onIntroDone: { 0277 hydro.item.start() 0278 } 0279 intro: [ 0280 qsTr("Tux has come back from fishing on his boat. " + 0281 "Bring the electrical system back up so he can have light in his home."), 0282 qsTr("Click on different active elements: sun, cloud, dam, solar array, " + 0283 "wind farm and transformers, in order to reactivate the entire electrical system."), 0284 qsTr("When the system is back up and Tux is in his home, push the light button for him. " + 0285 "To win you must switch on all the consumers while all the producers are up."), 0286 qsTr("Learn about an electrical system based on renewable energy. Enjoy.") 0287 ] 0288 } 0289 0290 Rectangle { 0291 id: check 0292 opacity: 0 0293 width: background.width * 0.9 0294 height: layoutArea.height * 0.9 0295 anchors.horizontalCenter: parent.horizontalCenter 0296 anchors.verticalCenter: layoutArea.verticalCenter 0297 z: 100 0298 border.width: 2 0299 radius: 5 0300 color: "#D2D2D2" 0301 property bool shown: false 0302 0303 GCText { 0304 id: warning 0305 anchors.centerIn: parent 0306 width: parent.width * 0.9 0307 height: parent.height * 0.9 0308 horizontalAlignment: Text.AlignHCenter 0309 verticalAlignment: Text.AlignVCenter 0310 text: qsTr( "It is not possible to consume more electricity " + 0311 "than what is produced. There is a key limitation in the " + 0312 "distribution of electricity, with minor exceptions, " + 0313 "electrical energy cannot be stored, and therefore it " + 0314 "must be generated as it is needed. A sophisticated " + 0315 "system of control is therefore required to ensure electric " + 0316 "generation very closely matches the demand. If supply and demand " + 0317 "are not in balance, generation plants and transmission equipment " + 0318 "can shut down which, in the worst cases, can lead to a major " + 0319 "regional blackout.") 0320 fontSizeMode: Text.Fit 0321 minimumPointSize: 8 0322 wrapMode: Text.WordWrap 0323 } 0324 0325 Behavior on opacity { 0326 NumberAnimation { 0327 duration: 200 0328 } 0329 } 0330 0331 MouseArea { 0332 anchors.fill: parent 0333 enabled: check.opacity > 0 0334 onClicked: check.opacity = 0 0335 } 0336 } 0337 0338 Image { 0339 id: stepDown 0340 z: 50 0341 source: activity.url + "transformer_off.svg" 0342 width: layoutArea.width * 0.07 0343 sourceSize.width: width 0344 fillMode: Image.PreserveAspectFit 0345 anchors { 0346 top: layoutArea.top 0347 left: layoutArea.left 0348 topMargin: layoutArea.width * 0.462 0349 leftMargin: layoutArea.width * 0.727 0350 } 0351 MouseArea { 0352 anchors.centerIn: parent 0353 // Size the area for a touch screen 0354 width: parent.width * 1.2 0355 height: parent.height * 1.2 0356 onClicked: { 0357 onClicked: parent.started = !parent.started 0358 } 0359 } 0360 property bool started: false 0361 property int powerIn: 0362 started ? (hydro.item.power + 0363 (wind.item ? wind.item.power : 0) + 0364 (solar.item ? solar.item.power : 0)) : 0 0365 property int powerOut: 0366 started ? (tux.powerConsumed + 0367 residentSmallLights.powerConsumed + 0368 residentBigLights.powerConsumed) : 0 0369 0370 onPowerInChanged: checkPower() 0371 0372 // Check powerOut does not exceed powerIn. Cut some consumers in case. 0373 function checkPower() { 0374 if(powerOut > powerIn && residentBigSwitch.on) { 0375 residentBigSwitch.on = false 0376 if(!check.shown && powerIn) check.opacity = 1 0377 } 0378 0379 if(!started || (powerOut > powerIn && residentSmallSwitch.on)) { 0380 residentSmallSwitch.on = false 0381 if(!check.shown && powerIn) check.opacity = 1 0382 } 0383 0384 if(!started || (powerOut > powerIn && tuxSwitch.on)) { 0385 tuxSwitch.on = false 0386 if(!check.shown && powerIn) check.opacity = 1 0387 } 0388 } 0389 } 0390 0391 Image { 0392 id: stepDownOn 0393 z: 50 0394 source: activity.url + "transformer_on.svg" 0395 anchors.fill: stepDown 0396 sourceSize.width: width 0397 fillMode: Image.PreserveAspectFit 0398 visible: stepDown.started 0399 } 0400 0401 Rectangle { 0402 id: produceMeter 0403 width: pow.width * 1.1 0404 height: pow.height * 1.1 0405 border.color: items.produceColorBorder 0406 radius: 5 0407 color: items.produceColor 0408 anchors { 0409 bottom: stepDown.top 0410 left: stepDown.horizontalCenter 0411 } 0412 GCText { 0413 id: pow 0414 anchors.centerIn: parent 0415 fontSize: smallSize * 0.5 0416 text: stepDown.powerIn.toString() + "W" 0417 } 0418 } 0419 0420 Image { 0421 id: stepDownWire 0422 source: activity.url + "hydroelectric/stepdownwire_off.svg" 0423 width: layoutArea.width * 0.154 0424 sourceSize.width: width 0425 fillMode: Image.PreserveAspectFit 0426 anchors { 0427 left: layoutArea.left 0428 top: layoutArea.top 0429 leftMargin: layoutArea.width * 0.623 0430 topMargin: layoutArea.width * 0.503 0431 } 0432 } 0433 0434 Image { 0435 id: stepDownWireOn 0436 source: activity.url + "hydroelectric/stepdownwire_on.svg" 0437 anchors.fill: stepDownWire 0438 sourceSize.width: width 0439 fillMode: Image.PreserveAspectFit 0440 visible: stepDown.powerIn > 0 0441 } 0442 0443 Image { 0444 id: consumerPole 0445 source: activity.url + "consumer_pole.svg" 0446 width: layoutArea.width * 0.037 0447 sourceSize.width: width 0448 fillMode: Image.PreserveAspectFit 0449 anchors { 0450 top: layoutArea.top 0451 left: layoutArea.left 0452 leftMargin: layoutArea.width * 0.681 0453 topMargin: layoutArea.width * 0.514 0454 } 0455 } 0456 0457 Rectangle { 0458 id: consumeMeter 0459 width: stepdown_info.width * 1.1 0460 height: stepdown_info.height * 1.1 0461 border.color: items.consumeColorBorder 0462 radius: 5 0463 color: items.consumeColor 0464 anchors { 0465 bottom: consumerPole.top 0466 right: consumerPole.horizontalCenter 0467 } 0468 GCText { 0469 id: stepdown_info 0470 anchors.centerIn: parent 0471 fontSize: smallSize * 0.5 0472 text: stepDown.powerOut.toString() + "W" 0473 } 0474 } 0475 0476 Image { 0477 id: tuxHouse 0478 source: activity.url2 + "tuxHouse.svg" 0479 width: layoutArea.width * 0.036 0480 sourceSize.width: width 0481 fillMode: Image.PreserveAspectFit 0482 anchors { 0483 top: layoutArea.top 0484 left: layoutArea.left 0485 topMargin: layoutArea.height * 0.638 0486 leftMargin: layoutArea.width * 0.765 0487 } 0488 } 0489 0490 Image { 0491 id: tuxHouseOn 0492 source: activity.url + "tux_house_on.svg" 0493 anchors.fill: tuxHouse 0494 sourceSize.width: width 0495 fillMode: Image.PreserveAspectFit 0496 visible: tuxSwitch.on 0497 } 0498 0499 Image { 0500 id: city 0501 source: activity.url2 + "city.svg" 0502 width: layoutArea.width * 0.202 0503 sourceSize.width: width 0504 fillMode: Image.PreserveAspectFit 0505 anchors { 0506 top: layoutArea.top 0507 left: layoutArea.left 0508 topMargin: layoutArea.height * 0.465 0509 leftMargin: layoutArea.width * 0.44 0510 } 0511 } 0512 0513 Image { 0514 id: residentSmallLights 0515 source: activity.url + "resident_smallon.svg" 0516 anchors.fill: city 0517 sourceSize.width: width 0518 fillMode: Image.PreserveAspectFit 0519 visible: items.currentLevel > 0 && powerConsumed 0520 property int power: 1000 0521 property int powerConsumed: on ? power : 0 0522 property bool on: residentSmallSwitch.on 0523 } 0524 0525 Image { 0526 id: residentSmallSwitch 0527 visible: items.currentLevel > 0 0528 source: activity.url + (on ? "on.svg" : "off.svg") 0529 width: layoutArea.width * 0.053 0530 sourceSize.width: width 0531 fillMode: Image.PreserveAspectFit 0532 anchors { 0533 left: layoutArea.left 0534 top: layoutArea.top 0535 leftMargin: layoutArea.width * 0.535 0536 topMargin: layoutArea.height * 0.608 0537 } 0538 property bool on: false 0539 MouseArea { 0540 id: small_area 0541 enabled: parent.visible 0542 anchors.centerIn: parent 0543 // Size the area for a touch screen 0544 width: parent.width * 1.2 0545 height: width 0546 onClicked: { 0547 if(stepDown.powerIn - stepDown.powerOut >= residentSmallLights.power) 0548 parent.on = !parent.on 0549 else 0550 parent.on = false 0551 0552 checkForNextLevel() 0553 } 0554 } 0555 } 0556 0557 Rectangle { 0558 id: smallConsumeRect 0559 width: small_consume.width * 1.1 0560 height: small_consume.height * 1.1 0561 border.color: items.consumeColorBorder 0562 radius: 5 0563 color: items.consumeColor 0564 anchors { 0565 top: residentSmallSwitch.bottom 0566 horizontalCenter: residentSmallSwitch.horizontalCenter 0567 } 0568 GCText { 0569 id: small_consume 0570 anchors.centerIn: parent 0571 text: residentSmallLights.powerConsumed.toString() + "W" 0572 fontSize: smallSize * 0.5 0573 } 0574 visible: items.currentLevel > 0 0575 } 0576 0577 Image { 0578 id: residentBigSwitch 0579 visible: items.currentLevel > 1 0580 source: activity.url + (on ? "on.svg" : "off.svg") 0581 width: layoutArea.width * 0.053 0582 sourceSize.width: width 0583 fillMode: Image.PreserveAspectFit 0584 anchors { 0585 left: layoutArea.left 0586 top: layoutArea.top 0587 leftMargin: layoutArea.width * 0.629 0588 topMargin: layoutArea.height * 0.608 0589 } 0590 property bool on: false 0591 MouseArea { 0592 id: big_area 0593 visible: parent.visible 0594 anchors.centerIn: parent 0595 // Size the area for a touch screen 0596 width: parent.width * 1.2 0597 height: width 0598 onClicked: { 0599 if(stepDown.powerIn - stepDown.powerOut >= residentBigLights.power) 0600 parent.on = !parent.on 0601 else 0602 parent.on = false 0603 0604 checkForNextLevel() 0605 } 0606 } 0607 } 0608 0609 Rectangle { 0610 id: bigConsumeRect 0611 width: bigConsume.width * 1.1 0612 height: bigConsume.height * 1.1 0613 border.color: items.consumeColorBorder 0614 radius : 5 0615 color: items.consumeColor 0616 anchors { 0617 top: residentBigSwitch.bottom 0618 horizontalCenter: residentBigSwitch.horizontalCenter 0619 } 0620 GCText { 0621 id: bigConsume 0622 anchors.centerIn: parent 0623 text: residentBigLights.powerConsumed.toString() + "W" 0624 fontSize: smallSize * 0.5 0625 } 0626 visible: items.currentLevel > 1 0627 } 0628 0629 Image { 0630 id: residentBigLights 0631 source: activity.url + "resident_bigon.svg" 0632 anchors.fill: city 0633 sourceSize.width: width 0634 fillMode: Image.PreserveAspectFit 0635 visible: items.currentLevel > 0 && powerConsumed 0636 property int power: 2000 0637 property int powerConsumed: on ? power : 0 0638 property bool on: residentBigSwitch.on 0639 } 0640 0641 // Tux is visible when tuxboat animation stops 0642 // It's light can be activated after stepdown is on 0643 0644 Image { 0645 id: tux 0646 source: activity.url + (on ? "lightson.svg" : "lightsoff.svg") 0647 width: layoutArea.width * 0.184 0648 sourceSize.width: width 0649 fillMode: Image.PreserveAspectFit 0650 anchors { 0651 top: layoutArea.top 0652 left: layoutArea.left 0653 leftMargin: layoutArea.width * 0.79 0654 topMargin: layoutArea.width * 0.557 0655 } 0656 visible: false 0657 property int power: 100 0658 property int powerConsumed: on ? power : 0 0659 property bool on: tuxSwitch.on 0660 } 0661 0662 Image { 0663 id: tuxSwitch 0664 source: activity.url + (on ? "on.svg" : "off.svg") 0665 width: layoutArea.width * 0.053 0666 sourceSize.width: width 0667 fillMode: Image.PreserveAspectFit 0668 property bool on: false 0669 visible: tux.visible 0670 anchors { 0671 top: layoutArea.top 0672 left: layoutArea.left 0673 leftMargin: layoutArea.width * 0.868 0674 topMargin: layoutArea.width * 0.722 0675 } 0676 MouseArea { 0677 id: off_area 0678 anchors.centerIn: parent 0679 // Size the area for a touch screen 0680 width: parent.width * 1.2 0681 height: width 0682 enabled: tuxSwitch.visible 0683 onClicked: { 0684 if(stepDown.powerIn - stepDown.powerOut >= tux.power) 0685 parent.on = !parent.on 0686 else 0687 parent.on = false 0688 checkForNextLevel() 0689 } 0690 } 0691 } 0692 0693 Rectangle { 0694 id: tuxMeter 0695 width: tuxConsume.width * 1.1 0696 height: tuxConsume.height * 1.1 0697 border.color: items.consumeColorBorder 0698 radius : 5 0699 color: items.consumeColor 0700 anchors { 0701 top: tuxSwitch.bottom 0702 horizontalCenter: tuxSwitch.horizontalCenter 0703 } 0704 GCText { 0705 id: tuxConsume 0706 anchors.centerIn: parent 0707 fontSize: smallSize * 0.5 0708 text: tux.powerConsumed.toString() + "W" 0709 } 0710 visible: tux.visible 0711 } 0712 0713 function win() { 0714 items.bonus.good("flower") 0715 } 0716 0717 DialogHelp { 0718 id: dialogHelp 0719 onClose: home() 0720 } 0721 0722 Bar { 0723 id: bar 0724 level: items.currentLevel + 1 0725 content: BarEnumContent { value: help | home | level | reload } 0726 onHelpClicked: displayDialog(dialogHelp) 0727 onPreviousLevelClicked: previousLevel() 0728 onNextLevelClicked: nextLevel() 0729 onHomeClicked: { 0730 if(message.visible) 0731 message.visible = false; 0732 home(); 0733 } 0734 onReloadClicked: initLevel() 0735 } 0736 0737 Bonus { 0738 id: bonus 0739 Component.onCompleted: win.connect(nextLevel) 0740 } 0741 } 0742 }