<?xml version="1.0" encoding="UTF-16"?>
<!-- This XML file has been created by WebEJS 1.0. Visit http://t.um.es/webejs -->
<!-- Please, open it with WebEJS or save the file to your hard disk on your EJS' user directory and open it with Desktop Ejs 6.01 or later. -->
<Osejs version="7.0" password="">
<Osejs.Information>
<Title><![CDATA[Electrolysis_Virtual_Lab_xAPI_v2]]></Title>
<Copyright><![CDATA[]]></Copyright>
<Keywords><![CDATA[]]></Keywords>
<Password><![CDATA[unused]]></Password>
<Level><![CDATA[]]></Level>
<Language><![CDATA[]]></Language>
<Abstract><![CDATA[]]></Abstract>
<FixedNavigationBar>false</FixedNavigationBar>
<RunAlways>true</RunAlways>
<UseInterpreter>true</UseInterpreter>
<UseDeltaForODE>false</UseDeltaForODE>
<PreviewFullModel>false</PreviewFullModel>
<ModelTab></ModelTab>
<ModelTabTitle><![CDATA[]]></ModelTabTitle>
<ModelName><![CDATA[]]></ModelName>
<CSSFile></CSSFile>
<HTMLHead><![CDATA[<script src="xapiwrapper.min.js"></script>

 <script>
    // Using a namespace to prevent global variable clashes
    const XAPIUtils = {
      parameters: null, // Parameters store
      getParameters: function () {
        if (!this.parameters) { // Ensure fetch once
          var urlParams = new URLSearchParams(window.location.search);
          var endpoint = urlParams.get('endpoint');
          var auth = urlParams.get('auth');
          var agent = JSON.parse(urlParams.get('agent'));
          var stateId = urlParams.get('stateId');
          var activityId = urlParams.get('activityId');

          ADL.XAPIWrapper.changeConfig({
            "endpoint": endpoint + "/",
            "auth": `Basic ${auth}`
          });

          this.parameters = {
            agent,
            stateId,
            activityId
          };
        }

        return this.parameters;
      }
    };

    // Immediately invoke getParameters on page load
    document.addEventListener("DOMContentLoaded", function() {
      XAPIUtils.getParameters(); // Fetch parameters once on load
    });

    function sendScore(score) {
      try {
        const parameters = XAPIUtils.getParameters(); // Retrieve parameters from store
        const activityid = parameters.activityId;
        const stateId = parameters.stateId;
        const agent = parameters.agent;
        const registration = null;

        const stateValue = {
          score: score
        };

        ADL.XAPIWrapper.sendState(activityid, agent, stateId, registration, stateValue);
      } catch (err) {
        console.error("An error has occurred!", err);
      }
    }
</script>

<script 
async="true" src="https://www.googletagmanager.com/gtag/js?id=G-S9EWRY1CPJ"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-S9EWRY1CPJ');
</script>]]></HTMLHead>
<SaveInXMLFormat>true</SaveInXMLFormat>
<IncludeSource>true</IncludeSource>
<IncludeLibrary>true</IncludeLibrary>
<UglifyJS>false</UglifyJS>
<Logo>./logoElectolysis.png</Logo>
<Author><![CDATA[sithu;lookang;storyboard by sheena]]></Author>
<AuthorLogo></AuthorLogo>
<DetectedFiles><![CDATA[./logoElectolysis.png]]></DetectedFiles>
<AuxiliaryFiles><![CDATA[;./xapiwrapper.min.js]]></AuxiliaryFiles>
</Osejs.Information>
<Osejs.Description>
</Osejs.Description>
<Osejs.Model>
<Osejs.Model.FramesPerSecond>20</Osejs.Model.FramesPerSecond>
<Osejs.Model.StepsPerDisplay>1</Osejs.Model.StepsPerDisplay>
<Osejs.Model.RealTimeVariable></Osejs.Model.RealTimeVariable>
<Osejs.Model.Autostart>false</Osejs.Model.Autostart>
<Osejs.Model.Variables>
<Osejs.Model.Variables.Page>
<Type>undefined</Type>
<Name>Var Table 1</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[numOfNegativeIons]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[int]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[posOfNegativeIons]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[stuckStatus]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodePos]]></Name>
<Value><![CDATA[{}]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodePos]]></Name>
<Value><![CDATA[{}]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[moleculeRad]]></Name>
<Value><![CDATA[0.05]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[numOfPositiveIons]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[int]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[posOfPositiveIons]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[positiveIonsTargetPositions]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIonsTargetPositions]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIonLabels]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[positiveIonLabels]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>Var Table 2</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[positiveIons]]></Name>
<Value><![CDATA[{}]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIons]]></Name>
<Value><![CDATA[{}]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIonsVisibility]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[positiveIonsVisibility]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[reactions]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[posOfAnodeProducts]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeProductsLabels]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeProductsVisibility]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[posOfCathodeProducts]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeProductsLabels]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeProductsVisibility]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>Var Table 3</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[anodeProductTarget]]></Name>
<Value><![CDATA[[-0.6, 0.7]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeProductTarget]]></Name>
<Value><![CDATA[[0.6, 0.7]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeProductsReachedTarget]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeProductsReachedTarget]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeTestTubeLevel]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeTestTubeLevel]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[positiveIonTypes]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIonTypes]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[solutionTypes]]></Name>
<Value><![CDATA[{}]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeElectronPositions]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeElectronVisibility]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeElectronReachedTarget]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeElectronPositions]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeElectronVisibility]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeElectronReachedTarget]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>Var Table 6</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[anodeElectronStartPos]]></Name>
<Value><![CDATA[[-0.6, -0.2]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeElectronEndPos]]></Name>
<Value><![CDATA[[-0.6, -1.1]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeElectronStartPos]]></Name>
<Value><![CDATA[[0.6, -0.9]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeElectronEndPos]]></Name>
<Value><![CDATA[[0.6, -0.2]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeFormula]]></Name>
<Value><![CDATA[""]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeFormula]]></Name>
<Value><![CDATA[""]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[overallFormula]]></Name>
<Value><![CDATA[""]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[showNonDischargedIons]]></Name>
<Value><![CDATA[true]]></Value>
<Type><![CDATA[boolean]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[speedFactor]]></Name>
<Value><![CDATA[1.0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[baseStepSize]]></Name>
<Value><![CDATA[0.02]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[colorMapping]]></Name>
<Value><![CDATA[{}]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeIonsBlinkingFrames]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeIonsBlinkingFrames]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[blinkingFrames]]></Name>
<Value><![CDATA[30]]></Value>
<Type><![CDATA[int]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>Var Table 8</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[positiveIonColors]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIonColors]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeProductsColors]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeProductsColors]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[defaultIonColor]]></Name>
<Value><![CDATA["blue"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[currentAnodeProductColor]]></Name>
<Value><![CDATA["blue"]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[currentCathodeProductColor]]></Name>
<Value><![CDATA["blue"]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[positiveIonBlinkingFrames]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[negativeIonBlinkingFrames]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[Object]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>font</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[fontSize]]></Name>
<Value><![CDATA[12]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[font]]></Name>
<Value><![CDATA["normal normal " + fontSize + "px"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[fontSmall]]></Name>
<Value><![CDATA["normal normal " + fontSize/2 + "px"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>xapi</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[totalScore]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[int]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
<Osejs.Model.Variables.Page>
<Type>VARIABLE_EDITOR</Type>
<Name>lookang</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<PageComment><![CDATA[]]></PageComment>
<Variable>
<Name><![CDATA[colorSolution]]></Name>
<Value><![CDATA["rgba(0,0,255,0.1)"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[font]]></Name>
<Value><![CDATA["normal normal large \"Times New Roman\", Times, serif"]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[anodeText]]></Name>
<Value><![CDATA["4 OH⁻ (aq) →  2 H₂O(l) + O₂  ​(g) + 4 e₋"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[cathodeText]]></Name>
<Value><![CDATA["2 H⁺ (aq)+2 e₋  → H₂ (g)"+"\n4 H⁺ (aq)+4 e₋  → 2 H₂ (g)"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[overallText]]></Name>
<Value><![CDATA["2 H₂O (l) → 2 H₂  (g)+O₂ ​(g)"]]></Value>
<Type><![CDATA[String]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[]]></Name>
<Value><![CDATA[]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
</Content>
</Osejs.Model.Variables.Page>
</Osejs.Model.Variables>
<Osejs.Model.Initialization>
<Osejs.Model.Initialization.Page>
<Type>CODE_EDITOR</Type>
<Name>solutionTypes</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
solutionTypes = {
    "dilute NaCl": {
        negativeIonTypes: [
          {
            formula: "OH¯",
            amount: 4,
          },
          {
            formula: "Cl¯",
            amount: 4,
          },
        ],
        positiveIonTypes: [
          {
            formula: "H⁺",
            amount: 4,
          },
          {
            formula: "Na⁺",
            amount: 4,
          },
        ],
        reactions: [
          {
            location: "anode", // Where the reaction occurs ("anode" or "cathode")
            reactants: ["OH¯", "OH¯", "OH¯", "OH¯"], // Array of reactant ion labels
            product: "O₂", // Product label
            electronsTransferred: 4,
          },
          {
            location: "cathode",
            //reactants: ["H⁺", "H⁺"],
            //product: "H₂",
            //electronsTransferred: 2,
            reactants: ["H⁺", "H⁺"], // Include 4 H⁺ ions to balance the 4 electrons
                product: "H₂",
                electronsTransferred: 4, // Change from 2 to 4
          },
          
        ],
        anodeFormula: "4 OH⁻ (aq) → 2 H₂O(l) + O₂ (g) + 4 e⁻",
        cathodeFormula: "2 H⁺ (aq) + 2 e⁻ → H₂ (g)\n4 H⁺ (aq) + 4 e⁻ → 2 H₂ (g)",
        overallFormula: "2 H₂O (l) → 2 H₂ (g) + O₂ (g)  \n"
    },
    "concentrated NaCl": {
        negativeIonTypes: [
          {
            formula: "OH¯",
            amount: 2,
          },
          {
            formula: "Cl¯",
            amount: 2,  // ✅ CHANGE THIS from 6 to 2
          },
        ],
        positiveIonTypes: [
          {
            formula: "H⁺",
            amount: 2,
          },
          {
            formula: "Na⁺",
            amount: 2,  // ✅ CHANGE THIS from 6 to 2
          },
        ],
        reactions: [
          {
            location: "anode", // Where the reaction occurs ("anode" or "cathode")
            reactants: ["Cl¯", "Cl¯"], // Array of reactant ion labels
            product: "Cl₂", // Product label
            electronsTransferred: 2,
          },
          {
            location: "cathode",
            reactants: ["H⁺", "H⁺"],
            product: "H₂",
            electronsTransferred: 2,
          },
        ],
        anodeFormula: "2 Cl⁻ (aq) → Cl₂ (g) + 2 e⁻",
        cathodeFormula: "2 H⁺ (aq) + 2 e⁻ → H₂ (g)",
        //overallFormula: "2 H₂O (l) + 2 Cl⁻ (aq) → H₂ (g) + Cl₂ (g) + 2 OH⁻ (aq) \n  "
        overallFormula: "2H⁺(aq) + 2Cl⁻(aq) → H₂(g) + Cl₂(g) \n"
    }
}

// Color Mapping for Ions and Products
colorMapping = {
  "OH¯": "green",
  "O₂": "green",
  "H⁺": "orange",
  "H₂": "orange",
  "Cl¯": "red",
  "Cl₂": "red",
  "Na⁺": "magenta",
  
  // **Default Color:**
  "Unknown": "grey"
};
]]></Code>
</Content>
</Osejs.Model.Initialization.Page>
<Osejs.Model.Initialization.Page>
<Type>undefined</Type>
<Name>init</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Object positions (Anode and Cathode) - 
// not the actual position of the anode/cathode but the boundary where molecules can stick to
anodePos = {
  position: { x: -0.6, y: -0.1 },
  size: { x: 0.1, y: 1 },
};

cathodePos = {
  position: { x: 0.6, y: -0.1 },
  size: { x: 0.1, y: 1 },
};

anodeProductTarget = [anodePos.position.x, (anodePos.position.y + anodePos.size.y)];
cathodeProductTarget = [cathodePos.position.x, (cathodePos.position.y + cathodePos.size.y)];


// Ion definitions
initSolution("dilute NaCl");



]]></Code>
</Content>
</Osejs.Model.Initialization.Page>
<Osejs.Model.Initialization.Page>
<Type>CODE_EDITOR</Type>
<Name>responsiveFont</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Get the viewport dimensions
var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
var percent = 0.05
// Calculate the font size based on viewport width or height
var fontSize = Math.min(viewportWidth * percent, viewportHeight * percent); // Adjust the multiplier as needed

// Set the font size
// Set the font size and font family (Comic Sans)
font = "normal normal " + fontSize * 0.5 + "px 'Comic Sans MS', 'Comic Sans', cursive";
fontSmall = "normal normal " + fontSize * 0.35  + "px 'Comic Sans MS', 'Comic Sans', cursive";

// Apply the font size to your elements
// For example, you can apply it to a specific element with a class
//document.getElementById("yourElementId").style.font = font;
]]></Code>
</Content>
</Osejs.Model.Initialization.Page>
<Osejs.Model.Initialization.Page>
<Type>CODE_EDITOR</Type>
<Name>TL msg</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// TL msg
if (_isMobile){
  //do nothing
  }
  
  else{
    // copy this into the initialization
// make the font bigger
var FONT = "1.5vw"
_view.plottingPanel.getMessageDecoration("TL").getFont().setFontSize(FONT);
_view.plottingPanel.getMessageDecoration("TR").getFont().setFontSize(FONT);
_view.plottingPanel.getMessageDecoration("BL").getFont().setFontSize(FONT);
_view.plottingPanel.getMessageDecoration("BR").getFont().setFontSize(FONT);

//_view.plottingPanel.getMessageDecoration("TL").getStyle().setFillColor("red");
    }
]]></Code>
</Content>
</Osejs.Model.Initialization.Page>
</Osejs.Model.Initialization>
<Osejs.Model.Evolution>
<Osejs.Model.Evolution.Page>
<Type>EVOLUTION_EDITOR</Type>
<Name>Evol Page 1</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
updatePositions();



]]></Code>
</Content>
</Osejs.Model.Evolution.Page>
</Osejs.Model.Evolution>
<Osejs.Model.Constraints>
</Osejs.Model.Constraints>
<Osejs.Model.Library>
<Osejs.Model.Library.Page>
<Type>undefined</Type>
<Name>getRandomPosition</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Function to generate a random position within the boundary, avoiding exclusion zones
function getRandomPosition() {
  let position;
  let validPosition = false;
  while (!validPosition) {
    var x = Math.random() * (1.4 * 2) + -1.4;
    var y = Math.random() * (0.4 * 2) + -0.4;
    position = [x, y];

    // Check if the position is within exclusion zones
    if (!isInExclusionZone(position)) {
      validPosition = true;
    }
  }
  return position;
}

// Function to check if a position is within an exclusion zone
function isInExclusionZone(position) {
  const exclusionMargin = 0.2; // Adjust as needed
  const [x, y] = position;

  // Define rectangles representing exclusion zones around the anode and cathode
  const anodeExclusion = rectContainsPoint(
    x,
    y,
    anodePos.position.x,
    anodePos.position.y,
    anodePos.size.x + exclusionMargin,
    anodePos.size.y + exclusionMargin
  );

  const cathodeExclusion = rectContainsPoint(
    x,
    y,
    cathodePos.position.x,
    cathodePos.position.y,
    cathodePos.size.x + exclusionMargin,
    cathodePos.size.y + exclusionMargin
  );

  return anodeExclusion || cathodeExclusion;
}

// Function to check if a point is within a rectangle
function rectContainsPoint(pointX, pointY, rectX, rectY, rectWidth, rectHeight) {
  var rectHalfWidth = rectWidth / 2;
  var rectHalfHeight = rectHeight / 2;

  var left = rectX - rectHalfWidth;
  var right = rectX + rectHalfWidth;
  var top = rectY - rectHalfHeight;
  var bottom = rectY + rectHalfHeight;

  return pointX >= left && pointX <= right && pointY >= top && pointY <= bottom;
}

]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>generateIons</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Generate arrays of ion objects
function generateIons(ionTypes) {
  let ions = [];
  ionTypes.forEach((ionType) => {
    for (let i = 0; i < ionType.amount; i++) {
      ions.push({
        position: getRandomPosition(),
        type: ionType.formula,
        stuck: false,
      });
    }
  });
  return ions;
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>updatePositions</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function updatePositions() {
  var allStuck = true; // Flag to check if all elements are stuck

  // Precompute constants
  const stepSize = baseStepSize * speedFactor; // Adjusted step size
  const reachThreshold = 0.01;
  const reachThresholdSquared = reachThreshold * reachThreshold;
  const minDistanceSquared = 0.0001 * 0.0001;

  // Update positions for positive ions
  for (let i = 0; i < posOfPositiveIons.length; i++) {
    if (!positiveIonsStuckStatus[i] && positiveIonsVisibility[i]) {
      allStuck = false; // At least one element is still moving

      // Get current and target positions
      let pos = posOfPositiveIons[i];
      let targetPos = positiveIonsTargetPositions[i];

      // Compute vector towards the target position
      let dx = targetPos[0] - pos[0];
      let dy = targetPos[1] - pos[1];
      let distanceSquared = dx * dx + dy * dy;

      if (distanceSquared > minDistanceSquared) {
        let distance = Math.sqrt(distanceSquared);
        let invDistance = 1 / distance;

        // Normalize the vector and compute movement
        let vx = dx * invDistance;
        let vy = dy * invDistance;
        let moveDistance = Math.min(stepSize, distance);

        // Update position
        pos[0] += vx * moveDistance;
        pos[1] += vy * moveDistance;

        // Check if the ion has reached close enough to the target position
        if (distanceSquared <= reachThresholdSquared) {
          pos[0] = targetPos[0];
          pos[1] = targetPos[1];
          positiveIonsStuckStatus[i] = true;
        }
      } else {
        // Ion has reached its target position
        pos[0] = targetPos[0];
        pos[1] = targetPos[1];
        positiveIonsStuckStatus[i] = true;
      }
    }
  }

  // Update positions for negative ions
  for (let i = 0; i < posOfNegativeIons.length; i++) {
    if (!negativeIonsStuckStatus[i] && negativeIonsVisibility[i]) {
      allStuck = false; // At least one element is still moving

      // Get current and target positions
      let pos = posOfNegativeIons[i];
      let targetPos = negativeIonsTargetPositions[i];

      // Compute vector towards the target position
      let dx = targetPos[0] - pos[0];
      let dy = targetPos[1] - pos[1];
      let distanceSquared = dx * dx + dy * dy;

      if (distanceSquared > minDistanceSquared) {
        let distance = Math.sqrt(distanceSquared);
        let invDistance = 1 / distance;

        // Normalize the vector and compute movement
        let vx = dx * invDistance;
        let vy = dy * invDistance;
        let moveDistance = Math.min(stepSize, distance);

        // Update position
        pos[0] += vx * moveDistance;
        pos[1] += vy * moveDistance;

        // Check if the ion has reached close enough to the target position
        if (distanceSquared <= reachThresholdSquared) {
          pos[0] = targetPos[0];
          pos[1] = targetPos[1];
          negativeIonsStuckStatus[i] = true;
        }
      } else {
        // Ion has reached its target position
        pos[0] = targetPos[0];
        pos[1] = targetPos[1];
        negativeIonsStuckStatus[i] = true;
      }
    }
  }

  // After updating positions, check for reactions
  checkForReactions();

  // Update positions for anode products
  for (let i = 0; i < posOfAnodeProducts.length; i++) {
    if (anodeProductsVisibility[i] && !anodeProductsReachedTarget[i]) {
        
      allStuck = false; // At least one product is still moving

      let pos = posOfAnodeProducts[i];
      let dx = anodeProductTarget[0] - pos[0];
      let dy = anodeProductTarget[1] - pos[1];
      let distanceSquared = dx * dx + dy * dy;

      if (distanceSquared > minDistanceSquared) {
        let distance = Math.sqrt(distanceSquared);
        let invDistance = 1 / distance;
        let vx = dx * invDistance;
        let vy = dy * invDistance;
        let moveDistance = Math.min(stepSize, distance);

        pos[0] += vx * moveDistance;
        pos[1] += vy * moveDistance ;
        

       // if (distance <= moveDistance) {
        if ((distance - anodeTestTubeLevel) <= moveDistance) {
            pos[0] = anodeProductTarget[0];
          pos[1] = anodeProductTarget[1];
         // pos[1] = anodeProductTarget[1] - anodeTestTubeLevel ;
          anodeProductsReachedTarget[i] = true;
          anodeProductsVisibility[i] = false; // Product disappears
          anodeTestTubeLevel += 0.05;
        }
      }
      
      else {
        pos[0] = anodeProductTarget[0];
        pos[1] = anodeProductTarget[1] - anodeTestTubeLevel ;
        anodeProductsReachedTarget[i] = true;
        anodeProductsVisibility[i] = false; // Product disappears
        anodeTestTubeLevel += 0.05;
      }
    }
  }

  // Update positions for cathode products
  for (let i = 0; i < posOfCathodeProducts.length; i++) {
    if (cathodeProductsVisibility[i] && !cathodeProductsReachedTarget[i]) {
      allStuck = false; // At least one product is still moving

      let pos = posOfCathodeProducts[i];
      let dx = cathodeProductTarget[0] - pos[0];
      let dy = cathodeProductTarget[1] - pos[1];
      let distanceSquared = dx * dx + dy * dy;

      if (distanceSquared > minDistanceSquared) {
        let distance = Math.sqrt(distanceSquared);
        let invDistance = 1 / distance;
        let vx = dx * invDistance;
        let vy = dy * invDistance;
        let moveDistance = Math.min(stepSize, distance);

        pos[0] += vx * moveDistance;
        pos[1] += vy * moveDistance;

        //if (distance <= moveDistance) {
        if ((distance - cathodeTestTubeLevel) <= moveDistance) { // make the bubbles disappear at the airlevel instead of the top of the testtube
          pos[0] = cathodeProductTarget[0];
          pos[1] = cathodeProductTarget[1];
          cathodeProductsReachedTarget[i] = true;
          cathodeProductsVisibility[i] = false; // Product disappears
          cathodeTestTubeLevel += 0.05;
        }
      } else {
        pos[0] = cathodeProductTarget[0];
        pos[1] = cathodeProductTarget[1];
        cathodeProductsReachedTarget[i] = true;
        cathodeProductsVisibility[i] = false; // Product disappears
        cathodeTestTubeLevel += 0.05;
      }
    }
  }

  // Update positions for anode electrons
  for (let i = 0; i < anodeElectronPositions.length; i++) {
    if (anodeElectronVisibility[i] && !anodeElectronReachedTarget[i]) {
      allStuck = false; // At least one element is still moving

      let pos = anodeElectronPositions[i];
      let dx = anodeElectronEndPos[0] - pos[0];
      let dy = anodeElectronEndPos[1] - pos[1];
      let distanceSquared = dx * dx + dy * dy;

      if (distanceSquared > minDistanceSquared) {
        let distance = Math.sqrt(distanceSquared);
        let invDistance = 1 / distance;
        let vx = dx * invDistance;
        let vy = dy * invDistance;
        let moveDistance = Math.min(stepSize, distance);

        pos[0] += vx * moveDistance;
        pos[1] += vy * moveDistance;

        if (distance <= moveDistance) {
          pos[0] = anodeElectronEndPos[0];
          pos[1] = anodeElectronEndPos[1];
          anodeElectronReachedTarget[i] = true;
          anodeElectronVisibility[i] = false; // Electron disappears
        }
      } else {
        pos[0] = anodeElectronEndPos[0];
        pos[1] = anodeElectronEndPos[1];
        anodeElectronReachedTarget[i] = true;
        anodeElectronVisibility[i] = false; // Electron disappears
      }
    }
  }

  // Update positions for cathode electrons
  for (let i = 0; i < cathodeElectronPositions.length; i++) {
    if (cathodeElectronVisibility[i] && !cathodeElectronReachedTarget[i]) {
      allStuck = false; // At least one element is still moving

      let pos = cathodeElectronPositions[i];
      let dx = cathodeElectronEndPos[0] - pos[0];
      let dy = cathodeElectronEndPos[1] - pos[1];
      let distanceSquared = dx * dx + dy * dy;

      if (distanceSquared > minDistanceSquared) {
        let distance = Math.sqrt(distanceSquared);
        let invDistance = 1 / distance;
        let vx = dx * invDistance;
        let vy = dy * invDistance;
        let moveDistance = Math.min(stepSize, distance);

        pos[0] += vx * moveDistance;
        pos[1] += vy * moveDistance;

        if (distance <= moveDistance) {
          pos[0] = cathodeElectronEndPos[0];
          pos[1] = cathodeElectronEndPos[1];
          cathodeElectronReachedTarget[i] = true;
          cathodeElectronVisibility[i] = false; // Electron disappears
        }
      } else {
        pos[0] = cathodeElectronEndPos[0];
        pos[1] = cathodeElectronEndPos[1];
        cathodeElectronReachedTarget[i] = true;
        cathodeElectronVisibility[i] = false; // Electron disappears
      }
    }
  }

  // Check if any ions or products are still moving
  if (
    positiveIonsVisibility.some((v, i) => !positiveIonsStuckStatus[i] && v) ||
    negativeIonsVisibility.some((v, i) => !negativeIonsStuckStatus[i] && v) ||
    positiveIonsVisibility.some((v, i) => (positiveIonBlinkingFrames[i] > 0 && positiveIonBlinkingFrames[i] < 22) && v) ||
    negativeIonsVisibility.some((v, i) => (negativeIonBlinkingFrames[i] > 0 && negativeIonBlinkingFrames[i] < 22) && v) ||
    anodeProductsVisibility.some((v, i) => !anodeProductsReachedTarget[i] && v) ||
    cathodeProductsVisibility.some((v, i) => !cathodeProductsReachedTarget[i] && v) ||
    anodeElectronVisibility.some((v, i) => !anodeElectronReachedTarget[i] && v) ||
    cathodeElectronVisibility.some((v, i) => !cathodeElectronReachedTarget[i] && v)
  ) {
    allStuck = false;
  }

  if (allStuck) {
    resetIons();
  }
}

]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>checkForReactions</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function checkForReactions() {
  reactions.forEach((reaction) => {
    const { reactants, product, location, electronsTransferred } = reaction;

    let ionLabels, ionPositions, ionStuckStatus, ionVisibility, ionColors;
    let productsPositions, productsLabels, productsVisibility, productsReachedTarget, productColors;
    let electronPositions, electronVisibility, electronReachedTarget, electronColors;
    let electronStartPos;
    let ionBlinkingFrames;

    if (location === "anode") {
      ionLabels = negativeIonLabels;
      ionPositions = posOfNegativeIons;
      ionStuckStatus = negativeIonsStuckStatus;
      ionVisibility = negativeIonsVisibility;
      ionBlinkingFrames = negativeIonBlinkingFrames;

      productsPositions = posOfAnodeProducts;
      productsLabels = anodeProductsLabels;
      productsVisibility = anodeProductsVisibility;
      productsReachedTarget = anodeProductsReachedTarget;
      productColors = anodeProductsColors;

      electronPositions = anodeElectronPositions;
      electronVisibility = anodeElectronVisibility;
      electronReachedTarget = anodeElectronReachedTarget;
      electronStartPos = anodeElectronStartPos;
    } else if (location === "cathode") {
      ionLabels = positiveIonLabels;
      ionPositions = posOfPositiveIons;
      ionStuckStatus = positiveIonsStuckStatus;
      ionVisibility = positiveIonsVisibility;
      ionBlinkingFrames = positiveIonBlinkingFrames;

      productsPositions = posOfCathodeProducts;
      productsLabels = cathodeProductsLabels;
      productsVisibility = cathodeProductsVisibility;
      productsReachedTarget = cathodeProductsReachedTarget;
      productColors = cathodeProductsColors;

      electronPositions = cathodeElectronPositions;
      electronVisibility = cathodeElectronVisibility;
      electronReachedTarget = cathodeElectronReachedTarget;
      electronStartPos = cathodeElectronStartPos;
    } else {
      return; // Invalid location
    }

    // Build a map of available ions by label
    const availableIonsMap = new Map();
    for (let i = 0; i < ionLabels.length; i++) {
      if (ionStuckStatus[i] && (ionVisibility[i] || (ionBlinkingFrames[i] !== 0 && ionBlinkingFrames[i] !== 22))) {
        const label = ionLabels[i];
        if (!availableIonsMap.has(label)) {
          availableIonsMap.set(label, []);
        }
        availableIonsMap.get(label).push(i);
      }
    }

    // Check if enough ions are available for the reaction
    const requiredIons = {};
    for (const label of reactants) {
      requiredIons[label] = (requiredIons[label] || 0) + 1;
    }

    let canReact = true;
    for (const label in requiredIons) {
      if (!availableIonsMap.has(label) || availableIonsMap.get(label).length < requiredIons[label]) {
        canReact = false;
        break;
      }
    }

    // Perform the reaction if possible
    while (canReact) {
        console.log(ionBlinkingFrames);
      // Remove the ions used in the reaction
  const combinationIndices = [];
  let allCanCreateProduct = true; // Flag to check if all ions can create a product

  // First, collect all indices and check if all can create a product
  for (const label of reactants) {
    const index = availableIonsMap.get(label).pop();
    combinationIndices.push(index);

    // If any ion does not have blinkingFrames[index] > 0, set flag to false
    if (ionBlinkingFrames[index] > 0) {
      allCanCreateProduct = false;
    }
  }

  // Now, handle each ion's visibility and blinking frames
  for (const index of combinationIndices) {
    if (allCanCreateProduct) {
      // All ions are ready to create a product
      ionVisibility[index] = false;
      // Optionally, reset blinking frames if needed
      ionBlinkingFrames[index] = 0;
    } else {
      // Handle blinking frames and visibility as before
      if (ionBlinkingFrames[index] % 7 === 0) {
        ionVisibility[index] = false;
      } else {
        ionVisibility[index] = true;
      }
      ionBlinkingFrames[index]--;
    }
  }
      
      if (allCanCreateProduct) {
      // Calculate average position for the product
      let avgX = 0;
      let avgY = 0;
      for (const index of combinationIndices) {
        avgX += ionPositions[index][0];
        avgY += ionPositions[index][1];
      }
      avgX /= combinationIndices.length;
      avgY /= combinationIndices.length;

      // Add the new product
      productsPositions.push([avgX, avgY]);
      productsLabels.push(product);
      productsVisibility.push(true);
      productsReachedTarget.push(false);
      productColors.push(colorMapping[product] || defaultIonColor);

      // Create electron animations
      for (let i = 0; i < electronsTransferred; i++) {
        const yOffset = i * (2 * moleculeRad);
        const position = [electronStartPos[0], electronStartPos[1] - yOffset];
        electronPositions.push(position);
        electronVisibility.push(true);
        electronReachedTarget.push(false);
      }
      }



      // Check if more reactions can occur
      canReact = true;
      for (const label in requiredIons) {
        if (availableIonsMap.get(label).length < requiredIons[label]) {
          canReact = false;
          break;
        }
      }
    }
  });
}

]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>assignTargetPositions</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Function to assign target positions along the object's edge
function assignTargetPositions(positionsArray, object) {
  var rectHalfHeight = object.size.y / 2;
  //console.log("rectHalfHeight"+ rectHalfHeight) //lookang
  var minY = object.position.y - rectHalfHeight + moleculeRad; // Lower starting position
  var maxY = object.position.y + rectHalfHeight - moleculeRad; // Higher target position

  var availableHeight = maxY - minY;
  var numElements = positionsArray.length;

  var maxElements = Math.floor(availableHeight / (2 * moleculeRad));

  var actualNumElements = Math.min(numElements, maxElements);

  var spacing = availableHeight / (actualNumElements - 1);

  var targetPositions = [];

  for (var i = 0; i < numElements; i++) {
    // Calculate yPos for each element
    var index = i % actualNumElements;
    var yPos = minY + index * spacing;
    yPos = clamp(yPos, minY, maxY);

    // For each element, calculate the closest edge based on its starting position
    var elementPos = positionsArray[i];
    var dxLeft = Math.abs(elementPos[0] - (object.position.x - object.size.x / 2));
    var dxRight = Math.abs(elementPos[0] - (object.position.x + object.size.x / 2));

    var targetX;
    if (dxLeft < dxRight) {
      // Closest to the left edge
      targetX = object.position.x - object.size.x / 2 - moleculeRad;
    } else {
      // Closest to the right edge
      targetX = object.position.x + object.size.x / 2 + moleculeRad;
    }

    var targetPos = [targetX, yPos];
    targetPositions.push(targetPos);
  }

  return targetPositions;
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>clamp</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Function to clamp a value between a minimum and maximum
function clamp(value, min, max) {
  return Math.max(min, Math.min(max, value));
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>circleRectCollision</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Function to detect collision between a circle and a rectangle
function circleRectCollision(circleX, circleY, circleRadius, rectX, rectY, rectWidth, rectHeight) {
  // Half dimensions of the rectangle
  var rectHalfWidth = rectWidth / 2;
  var rectHalfHeight = rectHeight / 2;

  // Closest point from the circle's center to the rectangle
  var closestX = clamp(circleX, rectX - rectHalfWidth, rectX + rectHalfWidth);
  var closestY = clamp(circleY, rectY - rectHalfHeight, rectY + rectHalfHeight);

  // Distance between the circle's center and the closest point
  var distanceX = circleX - closestX;
  var distanceY = circleY - closestY;

  // Check if the distance is less than the circle's radius
  var distanceSquared = distanceX * distanceX + distanceY * distanceY;
  return distanceSquared < circleRadius * circleRadius;
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>resetIons</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// Function to generate positions and labels for ions
function resetIons() {
    
  // Calculate the total number of negative and positive ions
  numOfNegativeIons = negativeIonTypes.reduce((total, ion) => total + ion.amount, 0);
  numOfPositiveIons = positiveIonTypes.reduce((total, ion) => total + ion.amount, 0);

  // Generate positions and labels for positive ions
  posOfPositiveIons = [];
  positiveIonLabels = [];
  positiveIonsVisibility = [];
  positiveIonsStuckStatus = [];
  positiveIonColors = [];
  positiveIonBlinkingFrames = [];

  positiveIonTypes.forEach((ionType) => {
    for (let i = 0; i < ionType.amount; i++) {
      posOfPositiveIons.push(getRandomPosition());
      positiveIonLabels.push(ionType.formula);
      positiveIonsVisibility.push(true); // Initially, all ions are visible
      positiveIonsStuckStatus.push(false); // Initially, not stuck
      positiveIonColors.push(colorMapping[ionType.formula] || defaultIonColor); // Default color if not mapped
      positiveIonBlinkingFrames.push(22);
    }
  });

  // Generate positions and labels for negative ions
  posOfNegativeIons = [];
  negativeIonLabels = [];
  negativeIonsVisibility = [];
  negativeIonsStuckStatus = [];
  negativeIonColors = [];
  negativeIonBlinkingFrames = [];

  negativeIonTypes.forEach((ionType) => {
    for (let i = 0; i < ionType.amount; i++) {
      posOfNegativeIons.push(getRandomPosition());
      negativeIonLabels.push(ionType.formula);
      negativeIonsVisibility.push(true); // Initially, all ions are visible
      negativeIonsStuckStatus.push(false); // Initially, not stuck
      negativeIonColors.push(colorMapping[ionType.formula] || defaultIonColor); // Default color if not mapped
      negativeIonBlinkingFrames.push(22);
    }
  });

  // Assign target positions during initialization
  positiveIonsTargetPositions = assignTargetPositions(posOfPositiveIons, cathodePos);
  negativeIonsTargetPositions = assignTargetPositions(posOfNegativeIons, anodePos);
  
  // Arrays to keep track of whether an ion is stuck
  positiveIonsStuckStatus = new Array(posOfPositiveIons.length).fill(false);
  negativeIonsStuckStatus = new Array(posOfNegativeIons.length).fill(false);
  
    // Hide non-discharged ions if the option is disabled
  if (!showNonDischargedIons) {
    // Determine which ions are involved in reactions
    const dischargedPositiveIons = new Set();
    const dischargedNegativeIons = new Set();

    reactions.forEach(reaction => {
      if (reaction.location === "cathode") {
        reaction.reactants.forEach(ion => dischargedPositiveIons.add(ion));
      } else if (reaction.location === "anode") {
        reaction.reactants.forEach(ion => dischargedNegativeIons.add(ion));
      }
    });

    // Hide positive ions not involved in cathode reactions
    for (let i = 0; i < positiveIonLabels.length; i++) {
      if (!dischargedPositiveIons.has(positiveIonLabels[i])) {
        positiveIonsVisibility[i] = false;
      }
    }

    // Hide negative ions not involved in anode reactions
    for (let i = 0; i < negativeIonLabels.length; i++) {
      if (!dischargedNegativeIons.has(negativeIonLabels[i])) {
        negativeIonsVisibility[i] = false;
      }
    }
  }
  
  // Clear products arrays
  posOfAnodeProducts = [];
  anodeProductsLabels = [];
  anodeProductsVisibility = [];
  anodeProductsReachedTarget = [];
  anodeProductsColors = [];

  posOfCathodeProducts = [];
  cathodeProductsLabels = [];
  cathodeProductsVisibility = [];
  cathodeProductsReachedTarget = [];
  cathodeProductsColors = [];
  
  // Clear electron elements
  anodeElectronPositions = [];
  anodeElectronVisibility = [];
  anodeElectronReachedTarget = [];

  cathodeElectronPositions = [];
  cathodeElectronVisibility = [];
  cathodeElectronReachedTarget = [];
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>initSolution</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
// initSolution

function initSolution(solutionType) {
  negativeIonTypes = solutionTypes[solutionType].negativeIonTypes;
  positiveIonTypes = solutionTypes[solutionType].positiveIonTypes;
  reactions = solutionTypes[solutionType].reactions;
  
  reactions.forEach(reaction => {
    if (reaction.location === "anode") {
      currentAnodeProductColor = colorMapping[reaction.product];
    } else if (reaction.location === "cathode") {
      currentCathodeProductColor = colorMapping[reaction.product];
    }
  });

  anodeFormula = solutionTypes[solutionType].anodeFormula;
  cathodeFormula = solutionTypes[solutionType].cathodeFormula;
  overallFormula = solutionTypes[solutionType].overallFormula;
  
  resetIons();
  anodeTestTubeLevel = 0;
  cathodeTestTubeLevel = 0;
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>toggleNonDischargedVisibility</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function toggleNonDischargedVisibility(){
    if (!showNonDischargedIons) {
    for (let i = 0; i < positiveIonLabels.length; i++) {
      if (!ionIsDischarged(positiveIonLabels[i])) {
        positiveIonsVisibility[i] = false;
      }
    }

    for (let i = 0; i < negativeIonLabels.length; i++) {
      if (!ionIsDischarged(negativeIonLabels[i])) {
        negativeIonsVisibility[i] = false;
      }
    }
  }
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
</Osejs.Model.Library>
<Osejs.Model.Elements>
</Osejs.Model.Elements>
</Osejs.Model>
<Osejs.HtmlView>
<Osejs.HtmlView.Page>
<Type>HTML_VIEW_EDITOR</Type>
<Name>HtmlView</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<SizeOption>0</SizeOption>
<X>0</X>
<Y>0</Y>
<Width>800</Width>
<Height>600</Height>
<KeepHidden>true</KeepHidden>
<RootProperties>
</RootProperties>
<Tree>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.Panel</Type>
<Name><![CDATA[panel]]></Name>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.Panel</Type>
<Name><![CDATA[controlPanel]]></Name>
<Parent><![CDATA[panel]]></Parent>
<Property name="Width"><![CDATA["100%"]]></Property>
<Property name="CSS"><![CDATA[{"display":"block"}]]></Property>
<Property name="Font"><![CDATA[font]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Label</Type>
<Name><![CDATA[label]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Text"><![CDATA["Electrolysis Virtual Lab"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ComboBox</Type>
<Name><![CDATA[comboBox]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Options"><![CDATA[Object.keys(solutionTypes)]]></Property>
<Property name="OnChange"><![CDATA[var opts = _view.comboBox.getProperty("SelectedOptions"); 
var option = (opts.length > 0) ? opts[0] : ""; // selected option 

initSolution(option);]]></Property>
<Property name="Font"><![CDATA[font]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[showNonDischarged]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Text"><![CDATA[showNonDischargedIons ? "Hide non-discharged" : "Show non-discharged"]]></Property>
<Property name="OnClick"><![CDATA[showNonDischargedIons = !showNonDischargedIons;
resetIons();]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[speed]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Text"><![CDATA[speedFactor === 1.0 ? "Slow speed" : "Normal speed"]]></Property>
<Property name="OnClick"><![CDATA[if (speedFactor === 1.0) {
  speedFactor = 0.6;
} else {
  speedFactor = 1.0;
}]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TwoStateButton</Type>
<Name><![CDATA[playPauseButton]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="TextOn"><![CDATA["Play▶"]]></Property>
<Property name="State"><![CDATA[_isPaused]]></Property>
<Property name="OnClick"><![CDATA[_play();

//xAPI included ensures no more than 2 scores are sent, even if the user repeatedly selects the same or different valid options.
var opts = _view.comboBox.getProperty("SelectedOptions"); 
var option = (opts.length > 0) ? opts[0] : ""; // selected option 



  if 
    (option === "dilute NaCl")  {
    sendScore(1);

  }
else if (option === "concentrated NaCl")  {
     sendScore(1);
   
  }]]></Property>
<Property name="TextOff"><![CDATA["Pause❚❚"]]></Property>
<Property name="OffClick"><![CDATA[_pause();]]></Property>
<Property name="Width"><![CDATA["10%"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[resetButton]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Text"><![CDATA["Reset↻"]]></Property>
<Property name="OnClick"><![CDATA[%_reset%]]></Property>
<Property name="Width"><![CDATA["10%"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[two]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Text"><![CDATA["+2"]]></Property>
<Property name="OnPress"><![CDATA[sendScore(2)]]></Property>
<Property name="Visibility"><![CDATA[false]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[five]]></Name>
<Parent><![CDATA[controlPanel]]></Parent>
<Property name="Text"><![CDATA["+5"]]></Property>
<Property name="OnPress"><![CDATA[sendScore(5)]]></Property>
<Property name="Visibility"><![CDATA[false]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.WrappedPanel</Type>
<Name><![CDATA[wrappedPanel]]></Name>
<Parent><![CDATA[panel]]></Parent>
<Property name="CSS"><![CDATA[{ "display":"block"}]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.PlottingPanel</Type>
<Name><![CDATA[plottingPanel]]></Name>
<Parent><![CDATA[wrappedPanel]]></Parent>
<Property name="MinimumX"><![CDATA[-2]]></Property>
<Property name="MaximumX"><![CDATA[2]]></Property>
<Property name="MinimumY"><![CDATA[-1.5]]></Property>
<Property name="MaximumY"><![CDATA[1.5]]></Property>
<Property name="Enabled"><![CDATA[true]]></Property>
<Property name="Width"><![CDATA["90%"]]></Property>
<Property name="SquareAspect"><![CDATA[true]]></Property>
<Property name="Height"><![CDATA["90vh"]]></Property>
<Property name="Gutters"><![CDATA[[0,0,0,0]]]></Property>
<Property name="MarginX"><![CDATA[0]]></Property>
<Property name="MarginY"><![CDATA[20]]></Property>
<Property name="YFixedTick"><![CDATA[-2]]></Property>
<Property name="XFixedTick"><![CDATA[-2]]></Property>
<Property name="YTickStep"><![CDATA[4]]></Property>
<Property name="XTickStep"><![CDATA[4]]></Property>
<Property name="XAutoTicks"><![CDATA[false]]></Property>
<Property name="YAutoTicks"><![CDATA[false]]></Property>
<Property name="TRMessage"><![CDATA["Cathode (Reduction)\n"+cathodeFormula]]></Property>
<Property name="TLMessage"><![CDATA["Anode (Oxidation)\n"+anodeFormula]]></Property>
<Property name="BRMessage"><![CDATA["Overall\n"+overallFormula]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>false</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[container]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[containerLeftBorder]]></Name>
<Parent><![CDATA[container]]></Parent>
<Property name="X"><![CDATA[-1.5]]></Property>
<Property name="SizeX"><![CDATA[0.03]]></Property>
<Property name="SizeY"><![CDATA[1.35]]></Property>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="Y"><![CDATA[0.09]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[containerRightBorder]]></Name>
<Parent><![CDATA[container]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="SizeX"><![CDATA[0.03]]></Property>
<Property name="SizeY"><![CDATA[1.35]]></Property>
<Property name="X"><![CDATA[1.5]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="Y"><![CDATA[0.09]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[containerBottomBorder]]></Name>
<Parent><![CDATA[container]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="SizeY"><![CDATA[0.03]]></Property>
<Property name="SizeX"><![CDATA[3.03]]></Property>
<Property name="Y"><![CDATA[-0.6]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[containerBackground]]></Name>
<Parent><![CDATA[container]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA[colorSolution]]></Property>
<Property name="SizeX"><![CDATA[2.965]]></Property>
<Property name="SizeY"><![CDATA[1.22]]></Property>
<Property name="Y"><![CDATA[0.02]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>false</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[battery]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Image2D</Type>
<Name><![CDATA[image]]></Name>
<Parent><![CDATA[battery]]></Parent>
<Property name="ImageUrl"><![CDATA["./battery.png"]]></Property>
<Property name="SizeX"><![CDATA[0.4]]></Property>
<Property name="SizeY"><![CDATA[0.3]]></Property>
<Property name="Y"><![CDATA[-1.15]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>false</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[wires]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[wireLeft1]]></Name>
<Parent><![CDATA[wires]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="SizeY"><![CDATA[0.49]]></Property>
<Property name="SizeX"><![CDATA[0.0135]]></Property>
<Property name="X"><![CDATA[-0.6]]></Property>
<Property name="Y"><![CDATA[-0.94]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[wireLeft2]]></Name>
<Parent><![CDATA[wires]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="Y"><![CDATA[-1.179]]></Property>
<Property name="SizeY"><![CDATA[0.0135]]></Property>
<Property name="X"><![CDATA[-0.4]]></Property>
<Property name="SizeX"><![CDATA[0.4]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[wireRight1]]></Name>
<Parent><![CDATA[wires]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="Y"><![CDATA[-0.94]]></Property>
<Property name="SizeY"><![CDATA[0.49]]></Property>
<Property name="X"><![CDATA[0.6]]></Property>
<Property name="SizeX"><![CDATA[0.0135]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[wireRight2]]></Name>
<Parent><![CDATA[wires]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Black"]]></Property>
<Property name="Y"><![CDATA[-1.179]]></Property>
<Property name="SizeY"><![CDATA[0.0135]]></Property>
<Property name="X"><![CDATA[0.4]]></Property>
<Property name="SizeX"><![CDATA[0.4]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[testTubes]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Tank</Type>
<Name><![CDATA[testTubeLeft]]></Name>
<Parent><![CDATA[testTubes]]></Parent>
<Property name="Rotate"><![CDATA[Math.PI]]></Property>
<Property name="SizeX"><![CDATA[0.3]]></Property>
<Property name="SizeY"><![CDATA[1.5]]></Property>
<Property name="X"><![CDATA[-0.6]]></Property>
<Property name="Y"><![CDATA[0.2]]></Property>
<Property name="Level"><![CDATA[Math.min(anodeTestTubeLevel, 1)]]></Property>
<Property name="LevelColor"><![CDATA[currentAnodeProductColor]]></Property>
<Property name="FillColor"><![CDATA[colorSolution]]></Property>
<Property name="DrawFill"><![CDATA[true]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Tank</Type>
<Name><![CDATA[testTubeRight]]></Name>
<Parent><![CDATA[testTubes]]></Parent>
<Property name="X"><![CDATA[0.6]]></Property>
<Property name="SizeX"><![CDATA[0.3]]></Property>
<Property name="SizeY"><![CDATA[1.5]]></Property>
<Property name="Rotate"><![CDATA[Math.PI]]></Property>
<Property name="Y"><![CDATA[0.2]]></Property>
<Property name="Level"><![CDATA[Math.min(cathodeTestTubeLevel, 1)]]></Property>
<Property name="LevelColor"><![CDATA[currentCathodeProductColor]]></Property>
<Property name="FillColor"><![CDATA[colorSolution]]></Property>
<Property name="DrawFill"><![CDATA[true]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>false</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[electrons]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[anodeElectrons]]></Name>
<Parent><![CDATA[electrons]]></Parent>
<Property name="FillColor"><![CDATA["Cyan"]]></Property>
<Property name="Position"><![CDATA[anodeElectronPositions]]></Property>
<Property name="Visibility"><![CDATA[anodeElectronVisibility.length ? anodeElectronVisibility : false]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[cathodeElectrons]]></Name>
<Parent><![CDATA[electrons]]></Parent>
<Property name="Position"><![CDATA[cathodeElectronPositions]]></Property>
<Property name="Visibility"><![CDATA[cathodeElectronVisibility.length ? cathodeElectronVisibility : false]]></Property>
<Property name="FillColor"><![CDATA["Cyan"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TextSet2D</Type>
<Name><![CDATA[anodeElectronText]]></Name>
<Parent><![CDATA[electrons]]></Parent>
<Property name="Text"><![CDATA["e"]]></Property>
<Property name="Position"><![CDATA[anodeElectronPositions]]></Property>
<Property name="Visibility"><![CDATA[anodeElectronVisibility.length ? anodeElectronVisibility : false]]></Property>
<Property name="Font"><![CDATA[fontSmall]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TextSet2D</Type>
<Name><![CDATA[cathodeElectronText]]></Name>
<Parent><![CDATA[electrons]]></Parent>
<Property name="Text"><![CDATA["e"]]></Property>
<Property name="Position"><![CDATA[cathodeElectronPositions]]></Property>
<Property name="Visibility"><![CDATA[cathodeElectronVisibility.length ? cathodeElectronVisibility : false]]></Property>
<Property name="Font"><![CDATA[fontSmall]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>false</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[anode]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[anodeBlock]]></Name>
<Parent><![CDATA[anode]]></Parent>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Yellow"]]></Property>
<Property name="SizeY"><![CDATA[1]]></Property>
<Property name="Y"><![CDATA[-0.2]]></Property>
<Property name="X"><![CDATA[-0.6]]></Property>
<Property name="SizeX"><![CDATA[0.1]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Text2D</Type>
<Name><![CDATA[anodeLabel]]></Name>
<Parent><![CDATA[anode]]></Parent>
<Property name="Text"><![CDATA["anode"]]></Property>
<Property name="Rotate"><![CDATA[Math.PI/2]]></Property>
<Property name="X"><![CDATA[-0.6]]></Property>
<Property name="Y"><![CDATA[-0.2]]></Property>
<Property name="Font"><![CDATA[font]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>false</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[cathode]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Shape2D</Type>
<Name><![CDATA[cathodeBlock]]></Name>
<Parent><![CDATA[cathode]]></Parent>
<Property name="X"><![CDATA[0.6]]></Property>
<Property name="Y"><![CDATA[-0.2]]></Property>
<Property name="SizeY"><![CDATA[1]]></Property>
<Property name="ShapeType"><![CDATA["RECTANGLE"]]></Property>
<Property name="FillColor"><![CDATA["Yellow"]]></Property>
<Property name="SizeX"><![CDATA[0.1]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Text2D</Type>
<Name><![CDATA[cathodeLabel]]></Name>
<Parent><![CDATA[cathode]]></Parent>
<Property name="Text"><![CDATA["cathode"]]></Property>
<Property name="Rotate"><![CDATA[Math.PI/2]]></Property>
<Property name="X"><![CDATA[0.6]]></Property>
<Property name="Y"><![CDATA[-0.2]]></Property>
<Property name="Font"><![CDATA[font]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.Group2D</Type>
<Name><![CDATA[molecules]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[negativeIons]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="NumberOfElements"><![CDATA[numOfNegativeIons]]></Property>
<Property name="Position"><![CDATA[posOfNegativeIons]]></Property>
<Property name="FillColor"><![CDATA[negativeIonColors]]></Property>
<Property name="Visibility"><![CDATA[negativeIonsVisibility]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[postiveIons]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="NumberOfElements"><![CDATA[numOfPositiveIons]]></Property>
<Property name="Position"><![CDATA[posOfPositiveIons]]></Property>
<Property name="FillColor"><![CDATA[positiveIonColors]]></Property>
<Property name="Visibility"><![CDATA[positiveIonsVisibility]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TextSet2D</Type>
<Name><![CDATA[negativeText]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="Text"><![CDATA[negativeIonLabels]]></Property>
<Property name="Position"><![CDATA[posOfNegativeIons]]></Property>
<Property name="NumberOfElements"><![CDATA[numOfNegativeIons]]></Property>
<Property name="FillColor"><![CDATA["White"]]></Property>
<Property name="Visibility"><![CDATA[negativeIonsVisibility]]></Property>
<Property name="Font"><![CDATA[fontSmall]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TextSet2D</Type>
<Name><![CDATA[positiveText]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="Text"><![CDATA[positiveIonLabels]]></Property>
<Property name="Position"><![CDATA[posOfPositiveIons]]></Property>
<Property name="NumberOfElements"><![CDATA[numOfPositiveIons]]></Property>
<Property name="FillColor"><![CDATA["White"]]></Property>
<Property name="Visibility"><![CDATA[positiveIonsVisibility]]></Property>
<Property name="Font"><![CDATA[fontSmall]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[anodeProducts]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="Position"><![CDATA[posOfAnodeProducts]]></Property>
<Property name="Visibility"><![CDATA[anodeProductsVisibility.length ? anodeProductsVisibility: false]]></Property>
<Property name="FillColor"><![CDATA[anodeProductsColors]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TextSet2D</Type>
<Name><![CDATA[anodeProductText]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="Text"><![CDATA[anodeProductsLabels]]></Property>
<Property name="Position"><![CDATA[posOfAnodeProducts]]></Property>
<Property name="Visibility"><![CDATA[anodeProductsVisibility.length ? anodeProductsVisibility : false]]></Property>
<Property name="FillColor"><![CDATA["White"]]></Property>
<Property name="Font"><![CDATA[fontSmall]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[cathodeProducts]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="Visibility"><![CDATA[cathodeProductsVisibility.length ? cathodeProductsVisibility: false]]></Property>
<Property name="Position"><![CDATA[posOfCathodeProducts]]></Property>
<Property name="FillColor"><![CDATA[cathodeProductsColors]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.TextSet2D</Type>
<Name><![CDATA[cathodeProductText]]></Name>
<Parent><![CDATA[molecules]]></Parent>
<Property name="Text"><![CDATA[cathodeProductsLabels]]></Property>
<Property name="Position"><![CDATA[posOfCathodeProducts]]></Property>
<Property name="Visibility"><![CDATA[cathodeProductsVisibility.length ? cathodeProductsVisibility : false]]></Property>
<Property name="FillColor"><![CDATA["White"]]></Property>
<Property name="Font"><![CDATA[fontSmall]]></Property>
</HtmlView.Element>
</Tree>
</Content>
</Osejs.HtmlView.Page>
</Osejs.HtmlView>
</Osejs>
