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 }