<?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[]]></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 
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></Logo>
<Author><![CDATA[]]></Author>
<AuthorLogo></AuthorLogo>
<DetectedFiles><![CDATA[]]></DetectedFiles>
<AuxiliaryFiles><![CDATA[]]></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>true</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[selectedLine]]></Name>
<Value><![CDATA["Vertical"]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[sideOptions]]></Name>
<Value><![CDATA[["Left", "Right"]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[selectedSide]]></Name>
<Value><![CDATA["Left"]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[graphX]]></Name>
<Value><![CDATA[6]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[graphY]]></Name>
<Value><![CDATA[6]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[lineX1]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[lineY1]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[lineX2]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[lineY2]]></Name>
<Value><![CDATA[0]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedPointsX]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedPointsY]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedPoints]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedPointIndex]]></Name>
<Value><![CDATA[-1]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[selectedPointIndex]]></Name>
<Value><![CDATA[-1]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[selectedPlottedPoints]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedLineX]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedLineY]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedSizeX]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[plottedSizeY]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[start]]></Name>
<Value><![CDATA[false]]></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[mirroredPointsX]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredPointsY]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredPoints]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[selectedMirroredPoints]]></Name>
<Value><![CDATA[[]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredPointIndex]]></Name>
<Value><![CDATA[-1]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredLineX]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredLineY]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredSizeX]]></Name>
<Value><![CDATA[[undefined]]]></Value>
<Type><![CDATA[double]]></Type>
<Dimension><![CDATA[]]></Dimension>
<Domain><![CDATA[]]></Domain>
<Comment><![CDATA[]]></Comment>
</Variable>
<Variable>
<Name><![CDATA[mirroredSizeY]]></Name>
<Value><![CDATA[[undefined]]]></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>
<Osejs.Model.Initialization>
<Osejs.Model.Initialization.Page>
<Type>undefined</Type>
<Name>init</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
initFunctions();
]]></Code>
</Content>
</Osejs.Model.Initialization.Page>
</Osejs.Model.Initialization>
<Osejs.Model.Evolution>
</Osejs.Model.Evolution>
<Osejs.Model.Constraints>
</Osejs.Model.Constraints>
<Osejs.Model.Library>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>initFunctions</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function initFunctions() {
    reset();
    initSeparationLine();
    initPlottedPoints();
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>reset</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function reset () {
    plottedPointsX = [];
    plottedPointsY = [];
    plottedPoints = [];
    selectedPlottedPoints = [];
    plottedPointIndex = -1;
    selectedPointIndex = -1;
    plottedLineX = [undefined];
    plottedLineY = [undefined];
    plottedSizeX = [undefined];
    plottedSizeY = [undefined];
    
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>undefined</Type>
<Name>initSeparationLine</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function initSeparationLine() {
    switch (selectedLine) {
        case "Vertical":
            lineX1 = graphX / 2;
            lineY1 = 0;
            lineX2 = 0;
            lineY2 = graphY;
            break;
        case "Horizontal":
            lineX1 = 0;
            lineY1 = graphY / 2;
            lineX2 = graphX;
            lineY2 = 0;
            break;
        case "Diagonal (+)":
            lineX1 = 0;
            lineY1 = 0;
            lineX2 = graphX;
            lineY2 = graphY;
            break;
        case "Diagonal (-)":
            lineX1 = 0;
            lineY1 = graphY;
            lineX2 = graphX;
            lineY2 = -graphY;
            break;
        default:
            break;
    }
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>initPlottedPoints</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function initPlottedPoints() {

    plottedPointIndex = -1;
    selectedPointIndex = -1;

    const tickSeparation = 1; // Assuming 1 tick separation for points
    const midX = graphX / 2; // Midpoint of X axis
    const midY = graphY / 2; // Midpoint of Y axis

    switch (selectedLine) {
        case "Vertical":
            if (selectedSide === "Left") {
                for (let x = 0; x <= midX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        plottedPointsX.push(x);
                        plottedPointsY.push(y);
                        plottedPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            } else {
                for (let x = midX; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        plottedPointsX.push(x);
                        plottedPointsY.push(y);
                         plottedPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            }
            break;

        case "Horizontal":
            if (selectedSide === "Top") {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = midY; y <= graphY; y += tickSeparation) {
                        plottedPointsX.push(x);
                        plottedPointsY.push(y);
                        plottedPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            } else {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= midY; y += tickSeparation) {
                        plottedPointsX.push(x);
                        plottedPointsY.push(y);
                        plottedPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            }
            break;

        case "Diagonal (+)":
            if (selectedSide === "Left") {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x - y <= midX - midY) {
                            plottedPointsX.push(x);
                            plottedPointsY.push(y);
                            plottedPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            } else {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x - y >= midX - midY) {
                            plottedPointsX.push(x);
                            plottedPointsY.push(y);
                            plottedPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            }
            break;

        case "Diagonal (-)":
            if (selectedSide === "Left") {
                 for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x + y <= midX + midY) {
                            plottedPointsX.push(x);
                            plottedPointsY.push(y);
                            plottedPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            } else {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x + y >= midX + midY) {
                            plottedPointsX.push(x);
                            plottedPointsY.push(y);
                            plottedPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            }
            break;

        default:
            break;
    }
    
    selectedPlottedPoints = Array(plottedPointsX.length).fill(0);
    
}

]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>onClickPlottedPoints</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function onClickPlottedPoints (plottedPointIndex) {
    if (selectedPointIndex === -1) {
        selectedPointIndex = plottedPointIndex;
        selectedPlottedPoints[selectedPointIndex] = 2;
    } else if (selectedPointIndex === plottedPointIndex) {
        selectedPointIndex = -1;
        selectedPlottedPoints[plottedPointIndex] = 0;
    } else {
        plottedLineX.push(plottedPointsX[selectedPointIndex]);
        plottedLineY.push(plottedPointsY[selectedPointIndex]);
        plottedLineX.push(plottedPointsX[plottedPointIndex]);
        plottedLineY.push(plottedPointsY[plottedPointIndex]);
        plottedLineX.push(undefined);
        plottedLineY.push(undefined);
        
        plottedSizeX.push(undefined);
        plottedSizeY.push(undefined);
        plottedSizeX.push(plottedPointsX[selectedPointIndex] - plottedPointsX[plottedPointIndex]);
        plottedSizeY.push(plottedPointsY[selectedPointIndex] - plottedPointsY[plottedPointIndex]);
        plottedSizeX.push(undefined);
        plottedSizeY.push(undefined);
        
        
        plottedPoints[selectedPointIndex].connected.push({x: plottedPointsX[plottedPointIndex], y: plottedPointsY[plottedPointIndex]})
        plottedPoints[plottedPointIndex].connected.push({x: plottedPointsX[selectedPointIndex], y: plottedPointsY[selectedPointIndex]})
        
        selectedPlottedPoints[selectedPointIndex] = 0
        selectedPointIndex = -1;
        plottedPointIndex = -1;
        
    }
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>initMirroredPoints</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function initMirroredPoints() {
    
    start = true;
    selectedPointIndex = -1;
    mirroredPointIndex = -1;
    mirroredLineX = [undefined];
    mirroredLineY = [undefined];
    mirroredSizeX = [undefined];
    mirroredSizeY = [undefined];
    mirroredPoints = [];
    
    const tickSeparation = 1; // Assuming 1 tick separation for points
    const midX = graphX / 2; // Midpoint of X axis
    const midY = graphY / 2; // Midpoint of Y axis

    switch (selectedLine) {
        case "Vertical":
            if (selectedSide === "Left") {
               for (let x = midX; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        mirroredPointsX.push(x);
                        mirroredPointsY.push(y);
                        mirroredPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            } else {
                 for (let x = 0; x <= midX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        mirroredPointsX.push(x);
                        mirroredPointsY.push(y);
                        mirroredPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            }
            break;

        case "Horizontal":
            if (selectedSide === "Top") {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= midY; y += tickSeparation) {
                        mirroredPointsX.push(x);
                        mirroredPointsY.push(y);
                        mirroredPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            } else {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = midY; y <= graphY; y += tickSeparation) {
                        mirroredPointsX.push(x);
                        mirroredPointsY.push(y);
                        mirroredPoints.push({
                            x,
                            y,
                            connected: []
                        })
                    }
                }
            }
            break;

        case "Diagonal (+)":
            if (selectedSide === "Left") {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x - y >= midX - midY) {
                            mirroredPointsX.push(x);
                            mirroredPointsY.push(y);
                            mirroredPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            } else {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x - y <= midX - midY) {
                            mirroredPointsX.push(x);
                            mirroredPointsY.push(y);
                            mirroredPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            }
            break;

        case "Diagonal (-)":
            if (selectedSide === "Left") {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x + y >= midX + midY) {
                            mirroredPointsX.push(x);
                            mirroredPointsY.push(y);
                            mirroredPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            } else {
                for (let x = 0; x <= graphX; x += tickSeparation) {
                    for (let y = 0; y <= graphY; y += tickSeparation) {
                        if (x + y <= midX + midY) {
                            mirroredPointsX.push(x);
                            mirroredPointsY.push(y);
                            mirroredPoints.push({
                                x,
                                y,
                                connected: []
                            })
                        }
                    }
                }
            }
            break;

        default:
            break;
    }
    
    selectedMirroredPoints = Array(mirroredPointsX.length).fill(0);
    
}

]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>onClickMirroredPoints</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function onClickMirroredPoints(mirroredPointIndex) {
    if (selectedPointIndex === -1) {
        selectedPointIndex = mirroredPointIndex;
        selectedMirroredPoints[selectedPointIndex] = 2;
    } else if (selectedPointIndex === mirroredPointIndex) {
        selectedPointIndex = -1;
        selectedMirroredPoints[mirroredPointIndex] = 0;
    } else {
        mirroredLineX.push(mirroredPointsX[mirroredPointIndex]);
        mirroredLineY.push(mirroredPointsY[mirroredPointIndex]);
        mirroredLineX.push(mirroredPointsX[mirroredPointIndex]);
        mirroredLineY.push(mirroredPointsY[mirroredPointIndex]);
        mirroredLineX.push(undefined);
        mirroredLineY.push(undefined);
        
        mirroredSizeX.push(undefined);
        mirroredSizeY.push(undefined);
        mirroredSizeX.push(mirroredPointsX[selectedPointIndex] - mirroredPointsX[mirroredPointIndex]);
        mirroredSizeY.push(mirroredPointsY[selectedPointIndex] - mirroredPointsY[mirroredPointIndex]);
        mirroredSizeX.push(undefined);
        mirroredSizeY.push(undefined);
        
        mirroredPoints[selectedPointIndex].connected.push({x: mirroredPointsX[mirroredPointIndex], y: mirroredPointsY[mirroredPointIndex]})
        mirroredPoints[mirroredPointIndex].connected.push({x: mirroredPointsX[selectedPointIndex], y: mirroredPointsY[selectedPointIndex]})
        
        selectedMirroredPoints[selectedPointIndex] = 0
        selectedPointIndex = -1;
        mirroredPointIndex = -1;
        
    }
}
]]></Code>
</Content>
</Osejs.Model.Library.Page>
<Osejs.Model.Library.Page>
<Type>CODE_EDITOR</Type>
<Name>checkAnswer</Name>
<Active>true</Active>
<Internal>false</Internal>
<Content>
<Comment><![CDATA[]]></Comment>
<Code><![CDATA[
function checkAnswer() {

    console.log("Original Points:", plottedPoints);

    switch (selectedLine) {
        case "Vertical":
            mirroredPoints.forEach(point => {
                if (selectedSide === "Left") {
                    point.x = graphX - point.x; 
                } else {
                    point.x = graphX - point.x; 
                }

                point.connected = point.connected.map(conn => ({
                    x: graphX - conn.x,
                    y: conn.y
                }));
            });
            break;

        case "Horizontal":
            mirroredPoints.forEach(point => {
                if (selectedSide === "Top") {
                    point.y = graphY - point.y; 
                } else {
                    point.y = graphY - point.y; 
                }

                point.connected = point.connected.map(conn => ({
                    x: conn.x,
                    y: graphY - conn.y
                }));
            });
            break;

        case "Diagonal (+)":
            mirroredPoints.forEach(point => {
                if (selectedSide === "Left") {
                    const temp = point.x;
                    point.x = point.y;
                    point.y = temp; 
                } else {
                    const temp = point.x;
                    point.x = point.y;
                    point.y = temp; 
                }

                point.connected = point.connected.map(conn => ({
                    x: conn.y,
                    y: conn.x
                }));
            });
            break;

        case "Diagonal (-)":
            mirroredPoints.forEach(point => {
                const reflectedX = graphX - point.y;
                const reflectedY = graphY - point.x;
        
                point.x = reflectedX;
                point.y = reflectedY;
        
                point.connected = point.connected.map(conn => {
                    const reflectedConnX = graphX - conn.y;
                    const reflectedConnY = graphY - conn.x;
                    return { x: reflectedConnX, y: reflectedConnY };
                });
            });
            break;

        default:
            console.log("Invalid line selection.");
            break;
    }

    console.log("Mirrored Points:", mirroredPoints);

    const isEqual = processAndCompare(mirroredPoints, plottedPoints);

    if (isEqual) {
        alert("Success! The mirrored points match the original plotted points.");
    } else {
        alert("Try again! The mirrored points do not match.");
    }
    
    initMirroredPoints();
        
    return mirroredPoints;
}

function breakConnections(points) {
    const pointsMap = new Map();

    points.forEach((point) => {
        pointsMap.set(`${point.x},${point.y}`, { ...point, connected: [] });
    });

    const newPoints = [];

    function gcd(a, b) {
        return b === 0 ? Math.abs(a) : gcd(b, a % b);
    }

    points.forEach((point) => {
        const originalConnections = [...point.connected];

        originalConnections.forEach((connection) => {
            const dx = connection.x - point.x;
            const dy = connection.y - point.y;

            const step = gcd(dx, dy);
            const stepX = dx / step;
            const stepY = dy / step;

            let x = point.x;
            let y = point.y;

            let prevKey = `${x},${y}`; 

            while (x !== connection.x || y !== connection.y) {
                x += stepX;
                y += stepY;

                const newPointKey = `${x},${y}`;

                if (!pointsMap.has(newPointKey)) {
                    newPoints.push({ x, y, connected: [] });
                    pointsMap.set(newPointKey, { x, y, connected: [] });
                }

                const currentPoint = pointsMap.get(newPointKey);
                const previousPoint = pointsMap.get(prevKey);

                if (!currentPoint.connected.some((p) => p.x === previousPoint.x && p.y === previousPoint.y)) {
                    currentPoint.connected.push({ x: previousPoint.x, y: previousPoint.y });
                }
                if (!previousPoint.connected.some((p) => p.x === currentPoint.x && p.y === currentPoint.y)) {
                    previousPoint.connected.push({ x: currentPoint.x, y: currentPoint.y });
                }

                prevKey = newPointKey;
            }
        });
    });

    return Array.from(pointsMap.values());
}

function compareUnorderedPoints(arr1, arr2) {
    if (arr1.length !== arr2.length) return false;

    const sortedArr1 = arr1.slice().sort((a, b) => (a.x - b.x) || (a.y - b.y));
    const sortedArr2 = arr2.slice().sort((a, b) => (a.x - b.x) || (a.y - b.y));

    return sortedArr1.every((point1, index) => {
        const point2 = sortedArr2[index];

        if (point1.x !== point2.x || point1.y !== point2.y) return false;

        const sortedConn1 = point1.connected.slice().sort((a, b) => (a.x - b.x) || (a.y - b.y));
        const sortedConn2 = point2.connected.slice().sort((a, b) => (a.x - b.x) || (a.y - b.y));

        if (sortedConn1.length !== sortedConn2.length) return false;
        return sortedConn1.every((conn1, connIndex) => {
            const conn2 = sortedConn2[connIndex];
            return conn1.x === conn2.x && conn1.y === conn2.y;
        });
    });
}

function processAndCompare(arr1, arr2) {
    const expandedArr1 = breakConnections(arr1);
    const expandedArr2 = breakConnections(arr2);
    
    console.log(expandedArr1);
    console.log(expandedArr1);

    return compareUnorderedPoints(expandedArr1, expandedArr2);
}
]]></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[wrapper]]></Name>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.Panel</Type>
<Name><![CDATA[firstRow]]></Name>
<Parent><![CDATA[wrapper]]></Parent>
<Property name="CSS"><![CDATA["{ margin-bottom: 10px }"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Label</Type>
<Name><![CDATA[desccription]]></Name>
<Parent><![CDATA[firstRow]]></Parent>
<Property name="Text"><![CDATA["Click on the points to create a line. Press 'Start' to draw its symmetrical counterpart"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.Panel</Type>
<Name><![CDATA[secondRow]]></Name>
<Parent><![CDATA[wrapper]]></Parent>
<Property name="CSS"><![CDATA["{ margin-bottom: 10px }"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ComboBox</Type>
<Name><![CDATA[line]]></Name>
<Parent><![CDATA[secondRow]]></Parent>
<Property name="CSS"><![CDATA["{ margin-right: 10px }"]]></Property>
<Property name="OnChange"><![CDATA[var opts = _view.line.getProperty("SelectedOptions");  
selectedLine = (opts.length > 0)? opts[0]:"";
if (selectedLine === "Horizontal") {
sideOptions = ["Top", "Bottom"];
selectedSide = "Top";
} else {
sideOptions = ["Left", "Right"];
selectedSide = selectedSide === "Right" ? "Right" : "Left";
}
console.log(selectedLine, selectedSide);
initFunctions();]]></Property>
<Property name="Options"><![CDATA[["Vertical", "Horizontal", "Diagonal (+)", "Diagonal (-)"]]]></Property>
<Property name="Disabled"><![CDATA[start]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ComboBox</Type>
<Name><![CDATA[side]]></Name>
<Parent><![CDATA[secondRow]]></Parent>
<Property name="CSS"><![CDATA["{ margin-right: 10px }"]]></Property>
<Property name="Options"><![CDATA[sideOptions]]></Property>
<Property name="OnChange"><![CDATA[var opts = _view.side.getProperty("SelectedOptions");  
selectedSide = (opts.length > 0)? opts[0]:"";
console.log(selectedLine, selectedSide);
initFunctions();]]></Property>
<Property name="Disabled"><![CDATA[start]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[start]]></Name>
<Parent><![CDATA[secondRow]]></Parent>
<Property name="Text"><![CDATA["Start"]]></Property>
<Property name="CSS"><![CDATA["{ margin-right: 10px }"]]></Property>
<Property name="OnPress"><![CDATA[initMirroredPoints();]]></Property>
<Property name="Disabled"><![CDATA[start]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[clearScenario]]></Name>
<Parent><![CDATA[secondRow]]></Parent>
<Property name="Text"><![CDATA["Clear Scnenario"]]></Property>
<Property name="OnPress"><![CDATA[_reset();]]></Property>
<Property name="CSS"><![CDATA["{ margin-right: 10px }"]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[check]]></Name>
<Parent><![CDATA[secondRow]]></Parent>
<Property name="Text"><![CDATA["check"]]></Property>
<Property name="CSS"><![CDATA["{ margin-right: 10px }"]]></Property>
<Property name="OnPress"><![CDATA[checkAnswer();]]></Property>
<Property name="Disabled"><![CDATA[start ? false : true]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Button</Type>
<Name><![CDATA[clearAnswer]]></Name>
<Parent><![CDATA[secondRow]]></Parent>
<Property name="Text"><![CDATA["Clear Answer"]]></Property>
<Property name="CSS"><![CDATA["{ margin-right: 10px }"]]></Property>
<Property name="OnPress"><![CDATA[initMirroredPoints();]]></Property>
<Property name="Disabled"><![CDATA[start ? false : true]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Expanded>true</Expanded>
<Type>Elements.PlottingPanel</Type>
<Name><![CDATA[plottingPanel]]></Name>
<Parent><![CDATA[wrapper]]></Parent>
<Property name="MinimumX"><![CDATA[0]]></Property>
<Property name="MaximumX"><![CDATA[graphX]]></Property>
<Property name="MinimumY"><![CDATA[0]]></Property>
<Property name="MaximumY"><![CDATA[graphY]]></Property>
<Property name="Enabled"><![CDATA[true]]></Property>
<Property name="AutoScaleX"><![CDATA[false]]></Property>
<Property name="Height"><![CDATA["500px"]]></Property>
<Property name="Width"><![CDATA["500px"]]></Property>
<Property name="AutoScaleY"><![CDATA[false]]></Property>
<Property name="Gutters"><![CDATA[[0,0,0,0]]]></Property>
<Property name="XFixedTick"><![CDATA[0]]></Property>
<Property name="YFixedTick"><![CDATA[0]]></Property>
<Property name="XTickStep"><![CDATA[1]]></Property>
<Property name="YTickStep"><![CDATA[1]]></Property>
<Property name="XAutoTicks"><![CDATA[false]]></Property>
<Property name="YAutoTicks"><![CDATA[false]]></Property>
<Property name="AxisXShow"><![CDATA[false]]></Property>
<Property name="AxisYShow"><![CDATA[false]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.Segment2D</Type>
<Name><![CDATA[separationLine]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
<Property name="SizeX"><![CDATA[lineX2]]></Property>
<Property name="SizeY"><![CDATA[lineY2]]></Property>
<Property name="X"><![CDATA[lineX1]]></Property>
<Property name="Y"><![CDATA[lineY1]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[plottedPoints]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
<Property name="X"><![CDATA[plottedPointsX]]></Property>
<Property name="Y"><![CDATA[plottedPointsY]]></Property>
<Property name="EnabledPosition"><![CDATA["ENABLED_NO_MOVE"]]></Property>
<Property name="SizeX"><![CDATA[0.2]]></Property>
<Property name="SizeY"><![CDATA[0.2]]></Property>
<Property name="ShapeType"><![CDATA["ELLIPSE"]]></Property>
<Property name="ElementInteracted"><![CDATA[plottedPointIndex]]></Property>
<Property name="OnPress"><![CDATA[onClickPlottedPoints(plottedPointIndex)]]></Property>
<Property name="FillColor"><![CDATA["LightGray"]]></Property>
<Property name="LineWidth"><![CDATA[selectedPlottedPoints]]></Property>
<Property name="Visibility"><![CDATA[start ? false : true]]></Property>
<Property name="NumberOfElements"><![CDATA[plottedPointsX.length]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.SegmentSet2D</Type>
<Name><![CDATA[plottedLine]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
<Property name="X"><![CDATA[plottedLineX]]></Property>
<Property name="Y"><![CDATA[plottedLineY]]></Property>
<Property name="LineWidth"><![CDATA[5]]></Property>
<Property name="LineColor"><![CDATA["Black"]]></Property>
<Property name="SizeX"><![CDATA[plottedSizeX]]></Property>
<Property name="SizeY"><![CDATA[plottedSizeY]]></Property>
<Property name="NumberOfElements"><![CDATA[plottedLineX.length]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.ShapeSet2D</Type>
<Name><![CDATA[mirroredPoints]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
<Property name="X"><![CDATA[mirroredPointsX]]></Property>
<Property name="Y"><![CDATA[mirroredPointsY]]></Property>
<Property name="EnabledPosition"><![CDATA["ENABLED_NO_MOVE"]]></Property>
<Property name="SizeX"><![CDATA[0.2]]></Property>
<Property name="SizeY"><![CDATA[0.2]]></Property>
<Property name="ShapeType"><![CDATA["ELLIPSE"]]></Property>
<Property name="ElementInteracted"><![CDATA[mirroredPointIndex]]></Property>
<Property name="OnPress"><![CDATA[onClickMirroredPoints(mirroredPointIndex)]]></Property>
<Property name="FillColor"><![CDATA["LightGray"]]></Property>
<Property name="LineWidth"><![CDATA[selectedMirroredPoints]]></Property>
<Property name="NumberOfElements"><![CDATA[plottedPointsX.length]]></Property>
<Property name="Visibility"><![CDATA[start]]></Property>
</HtmlView.Element>
<HtmlView.Element>
<Type>Elements.SegmentSet2D</Type>
<Name><![CDATA[mirroredLine]]></Name>
<Parent><![CDATA[plottingPanel]]></Parent>
<Property name="X"><![CDATA[mirroredLineX]]></Property>
<Property name="Y"><![CDATA[mirroredLineY]]></Property>
<Property name="LineWidth"><![CDATA[5]]></Property>
<Property name="LineColor"><![CDATA["Black"]]></Property>
<Property name="SizeX"><![CDATA[mirroredSizeX]]></Property>
<Property name="SizeY"><![CDATA[mirroredSizeY]]></Property>
<Property name="NumberOfElements"><![CDATA[mirroredLineX.length]]></Property>
</HtmlView.Element>
</Tree>
</Content>
</Osejs.HtmlView.Page>
</Osejs.HtmlView>
</Osejs>