import ArrowLeftIcon from '@mui/icons-material/ArrowLeft';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
import PauseIcon from '@mui/icons-material/Pause';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import QuestionMarkIcon from '@mui/icons-material/QuestionMark';
import ReplayIcon from '@mui/icons-material/Replay';
import { Box, Button, Checkbox, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, FormControl, FormControlLabel, FormGroup, IconButton, LinearProgress, Stack } from '@mui/material';
import Typography from '@mui/material/Typography';
import { observer } from 'mobx-react';
import { HeightSym, NumListCast, WidthSym } from '../../../../fields/Doc';
import { ViewBoxAnnotatableComponent } from '../../DocComponent';
import { FieldView, FieldViewProps } from './../FieldView';
import './PhysicsSimulationBox.scss';
import InputField from './PhysicsSimulationInputField';
import * as questions from './PhysicsSimulationQuestions.json';
import * as tutorials from './PhysicsSimulationTutorial.json';
import Wall from './PhysicsSimulationWall';
import Weight from './PhysicsSimulationWeight';
import React = require('react');
import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
import { List } from '../../../../fields/List';

interface IWallProps {
    length: number;
    xPos: number;
    yPos: number;
    angleInDegrees: number;
}
interface IForce {
    description: string;
    magnitude: number;
    directionInDegrees: number;
    component: boolean;
}
interface VectorTemplate {
    top: number;
    left: number;
    width: number;
    height: number;
    x1: number;
    y1: number;
    x2: number;
    y2: number;
    weightX: number;
    weightY: number;
}
interface QuestionTemplate {
    questionSetup: string[];
    variablesForQuestionSetup: string[];
    question: string;
    answerParts: string[];
    answerSolutionDescriptions: string[];
    goal: string;
    hints: { description: string; content: string }[];
}

interface TutorialTemplate {
    question: string;
    steps: {
        description: string;
        content: string;
        forces: {
            description: string;
            magnitude: number;
            directionInDegrees: number;
            component: boolean;
        }[];
        show_Magnitude: boolean;
    }[];
}

@observer
export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
    public static LayoutString(fieldKey: string) {
        return FieldView.LayoutString(PhysicsSimulationBox, fieldKey);
    }

    constructor(props: any) {
        super(props);
    }

    // Constants
    xMin = 0;
    yMin = 0;
    xMax = 100;
    yMax = 100;
    color = `rgba(0,0,0,0.5)`;
    radius = 50;
    wallPositions: IWallProps[] = [];

    componentDidMount() {
        // Used throughout sims
        this.layoutDoc._width = 1000;
        this.layoutDoc._height = 800;
        this.xMax = this.layoutDoc._width * 0.6;
        this.yMax = this.layoutDoc._height * 0.9;
        this.dataDoc.componentForces = this.dataDoc.componentForces ?? [];
        this.dataDoc.gravity = NumCast(this.dataDoc.gravity, -9.81);
        this.dataDoc.mass = NumCast(this.dataDoc.mass, 1);
        this.dataDoc.mode = 'Freeform';
        this.dataDoc.show_ComponentForces = this.dataDoc.show_ComponentForces ?? false;
        this.dataDoc.simulation_Speed = NumCast(this.dataDoc.simulation_Speed, 2);
        this.dataDoc.simulation_Type = StrCast(this.dataDoc.simulation_Type, 'Inclined Plane');
        this.dataDoc.start_Forces = this.dataDoc.start_Forces ?? [];
        this.dataDoc.start_PosX = this.dataDoc.start_PosX ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
        this.dataDoc.start_PosY = this.dataDoc.start_PosY ?? this.getDisplayYPos((400 - 0.08 * this.layoutDoc._height) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26));
        this.dataDoc.stepNumber = NumCast(this.dataDoc.stepNumber);
        this.dataDoc.updatedForces = this.dataDoc.updatedForces ?? [];

        // Used for review mode
        // this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
        // this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
        // this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
        this.dataDoc.answers = new List<number>();
        this.dataDoc.show_Icon = false;
        this.dataDoc.hintDialogueOpen = false;
        this.dataDoc.noMovement = false;
        this.dataDoc.questionNumber = 0;
        this.dataDoc.questionPartOne = '';
        this.dataDoc.questionPartTwo = '';
        this.dataDoc.review_GravityAngle = 0;
        this.dataDoc.review_GravityMagnitude = 0;
        this.dataDoc.review_NormalAngle = 0;
        this.dataDoc.review_NormalMagnitude = 0;
        this.dataDoc.review_StaticAngle = 0;
        this.dataDoc.review_StaticMagnitude = 0;
        this.dataDoc.selectedSolutions = [];
        this.dataDoc.selectedQuestion = this.dataDoc.selectedQuestion ?? questions.inclinePlane[0];
        // this.dataDoc.sketching = this.dataDoc.sketching ?? false;

        // Used for tutorial mode
        this.dataDoc.selectedTutorial = this.dataDoc.selectedTutorial ?? tutorials.inclinePlane;

        // Used for uniform circular motion
        this.dataDoc.circularMotionRadius = this.dataDoc.circularMotionRadius ?? 150;

        // Used for spring simulation
        this.dataDoc.springConstant = NumCast(this.dataDoc.springConstant, 0.5);
        this.dataDoc.springRestLength = NumCast(this.dataDoc.springRestLength, 200);
        this.dataDoc.springStartLength = NumCast(this.dataDoc.springStartLength, 200);

        // Used for pendulum simulation
        this.dataDoc.pendulum_length = NumCast(this.dataDoc.pendulum_length, 300);

        // Used for wedge simulation
        this.dataDoc.wedgeAngle = NumCast(this.dataDoc.wedgeAngle, 26);
        this.dataDoc.wedgeHeight = NumCast(this.dataDoc.wedgeHeight, Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5);
        this.dataDoc.wedgeWidth = NumCast(this.dataDoc.wedgeWidth, this.xMax * 0.5);

        // Used for pulley simulation
        this.dataDoc.start_Forces2 = this.dataDoc.start_Forces2 ?? [];
        this.dataDoc.updatedForces2 = this.dataDoc.updatedForces2 ?? [];
        this.dataDoc.mass2 = NumCast(this.dataDoc.mass2, 1);

        // Setup simulation
        this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));

        // Create walls
        let walls = [];
        walls.push({ length: (this.xMax / this.layoutDoc._width) * 100, xPos: 0, yPos: 0, angleInDegrees: 0 });
        walls.push({ length: (this.xMax / this.layoutDoc._width) * 100, xPos: 0, yPos: (this.yMax / this.layoutDoc._height) * 100, angleInDegrees: 0 });
        walls.push({ length: (this.yMax / this.layoutDoc._height) * 100, xPos: 0, yPos: 0, angleInDegrees: 90 });
        walls.push({ length: (this.yMax / this.layoutDoc._height) * 100, xPos: (this.xMax / this.layoutDoc._width) * 100, yPos: 0, angleInDegrees: 90 });
        this.wallPositions = walls;
    }

    componentDidUpdate() {
        if (this.xMax !== this.layoutDoc[WidthSym]() * 0.6 || this.yMax != this.layoutDoc[HeightSym]() * 0.9) {
            this.layoutDoc._width = Math.max(this.layoutDoc[WidthSym](), 800);
            this.layoutDoc._height = Math.max(this.layoutDoc[HeightSym](), 600);
            this.xMax = this.layoutDoc._width * 0.6;
            this.yMax = this.layoutDoc._height * 0.9;
            this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
        }
    }

    setupSimulation = (simulationType: string, mode: string) => {
        this.dataDoc.simulation_Paused = true;
        if (simulationType != 'Circular Motion') {
            this.dataDoc.start_VelX = 0;
            this.dataDoc.setStartVelY = 0;
            this.dataDoc.velocity_XDisplay = 0;
            this.dataDoc.velocity_YDisplay = 0;
        }
        if (mode == 'Freeform') {
            this.dataDoc.show_ForceMagnitudes = true;
            if (simulationType == 'One Weight') {
                this.dataDoc.show_ComponentForces = false;
                this.dataDoc.start_PosY = this.yMin + 0.08 * this.layoutDoc[HeightSym]();
                this.dataDoc.start_PosX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                this.dataDoc.position_YDisplay = this.getDisplayYPos(this.yMin + 0.08 * this.layoutDoc[HeightSym]());
                this.dataDoc.position_XDisplay = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                this.dataDoc.updatedForces = [
                    {
                        description: 'Gravity',
                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                        directionInDegrees: 270,
                        component: false,
                    },
                ];
                this.dataDoc.start_Forces = [
                    {
                        description: 'Gravity',
                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                        directionInDegrees: 270,
                        component: false,
                    },
                ];
                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
            } else if (simulationType == 'Inclined Plane') {
                this.changeWedgeBasedOnNewAngle(26);
                this.dataDoc.start_Forces = [
                    {
                        description: 'Gravity',
                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                        directionInDegrees: 270,
                        component: false,
                    },
                ];
                this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction));
            } else if (simulationType == 'Pendulum') {
                this.setupPendulum();
            } else if (simulationType == 'Spring') {
                this.setupSpring();
            } else if (simulationType == 'Circular Motion') {
                this.setupCircular(0);
            } else if (simulationType == 'Pulley') {
                this.setupPulley();
            } else if (simulationType == 'Suspension') {
                this.setupSuspension();
            }
        } else if (mode == 'Review') {
            this.dataDoc.show_ComponentForces = false;
            this.dataDoc.show_ForceMagnitudes = true;
            this.dataDoc.show_Acceleration = false;
            this.dataDoc.show_Velocity = false;
            this.dataDoc.show_Forces = true;
            this.generateNewQuestion();
            if (simulationType == 'One Weight') {
                // TODO - one weight review problems
            } else if (simulationType == 'Spring') {
                this.setupSpring();
                // TODO - spring review problems
            } else if (simulationType == 'Inclined Plane') {
                this.dataDoc.updatedForces = [];
                this.dataDoc.start_Forces = [];
            } else if (simulationType == 'Pendulum') {
                this.setupPendulum();
                // TODO - pendulum review problems
            } else if (simulationType == 'Circular Motion') {
                this.setupCircular(0);
                // TODO - circular motion review problems
            } else if (simulationType == 'Pulley') {
                this.setupPulley();
                // TODO - pulley tutorial review problems
            } else if (simulationType == 'Suspension') {
                this.setupSuspension();
                // TODO - suspension tutorial review problems
            }
        } else if (mode == 'Tutorial') {
            this.dataDoc.show_ComponentForces = false;
            this.dataDoc.stepNumber = 0;
            this.dataDoc.show_Acceleration = false;
            if (this.dataDoc.simulation_Type != 'Circular Motion') {
                this.dataDoc.velocity_XDisplay = 0;
                this.dataDoc.velocity_YDisplay = 0;
                this.dataDoc.show_Velocity = false;
            } else {
                this.dataDoc.velocity_XDisplay = 20;
                this.dataDoc.velocity_YDisplay = 0;
                this.dataDoc.show_Velocity = true;
            }

            if (this.dataDoc.simulation_Type == 'One Weight') {
                this.dataDoc.show_Forces = true;
                this.dataDoc.start_PosY = this.yMax - 100;
                this.dataDoc.start_PosX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                this.dataDoc.selectedTutorial = tutorials.freeWeight;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.freeWeight.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
            } else if (this.dataDoc.simulation_Type == 'Spring') {
                this.dataDoc.show_Forces = true;
                this.setupSpring();
                this.dataDoc.start_PosY = this.yMin + 200 + 19.62;
                this.dataDoc.start_PosX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                this.dataDoc.selectedTutorial = tutorials.spring;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.spring.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
            } else if (this.dataDoc.simulation_Type == 'Pendulum') {
                this.dataDoc.show_Forces = true;
                const length = 300;
                const angle = 30;
                const x = length * Math.cos(((90 - angle) * Math.PI) / 180);
                const y = length * Math.sin(((90 - angle) * Math.PI) / 180);
                const xPos = this.xMax / 2 - x - 0.08 * this.layoutDoc[HeightSym]();
                const yPos = y - 0.08 * this.layoutDoc[HeightSym]() - 5;
                this.dataDoc.start_PosX = xPos;
                this.dataDoc.start_PosY = yPos;
                this.dataDoc.selectedTutorial = tutorials.pendulum;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.pendulum.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
                this.dataDoc.pendulum_angle = 30;
                this.dataDoc.pendulum_length = 300;
                this.dataDoc.pendulum_angle_adjust = 30;
                this.dataDoc.pendulum_length_adjust = 300;
            } else if (this.dataDoc.simulation_Type == 'Inclined Plane') {
                this.dataDoc.show_Forces = true;
                this.dataDoc.wedgeAngle = 26;
                this.changeWedgeBasedOnNewAngle(26);
                this.dataDoc.selectedTutorial = tutorials.inclinePlane;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
            } else if (this.dataDoc.simulation_Type == 'Circular Motion') {
                this.dataDoc.show_Forces = true;
                this.setupCircular(40);
                this.dataDoc.selectedTutorial = tutorials.circular;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.circular.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
            } else if (this.dataDoc.simulation_Type == 'Pulley') {
                this.dataDoc.show_Forces = true;
                this.setupPulley();
                this.dataDoc.selectedTutorial = tutorials.pulley;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.pulley.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
            } else if (this.dataDoc.simulation_Type == 'Suspension') {
                this.dataDoc.show_Forces = true;
                this.setupSuspension();
                this.dataDoc.selectedTutorial = tutorials.suspension;
                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.suspension.steps[0].forces);
                this.dataDoc.show_ForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
            }
            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
        }
    };

    // Helper function to go between display and real values
    getDisplayYPos = (yPos: number) => {
        return this.yMax - yPos - 2 * (0.08 * this.layoutDoc[HeightSym]()) + 5;
    };
    getYPosFromDisplay = (yDisplay: number) => {
        return this.yMax - yDisplay - 2 * (0.08 * this.layoutDoc[HeightSym]()) + 5;
    };

    // Update forces when coefficient of static friction changes in freeform mode
    updateForcesWithFriction = (coefficient: number, width: number = NumCast(this.dataDoc.wedgeWidth), height: number = NumCast(this.dataDoc.wedgeHeight)) => {
        const normalForce: IForce = {
            description: 'Normal Force',
            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass),
            directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
            component: false,
        };
        let frictionForce: IForce = {
            description: 'Static Friction Force',
            magnitude: coefficient * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass),
            directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI,
            component: false,
        };
        // reduce magnitude or friction force if necessary such that block cannot slide up plane
        let yForce = -Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass);
        yForce += normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180);
        yForce += frictionForce.magnitude * Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
        if (yForce > 0) {
            frictionForce.magnitude =
                (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass)) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
        }
        const frictionForceComponent: IForce = {
            description: 'Static Friction Force',
            magnitude: coefficient * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(Math.atan(height / width)),
            directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI,
            component: true,
        };
        const normalForceComponent: IForce = {
            description: 'Normal Force',
            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(Math.atan(height / width)),
            directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
            component: true,
        };
        const gravityParallel: IForce = {
            description: 'Gravity Parallel Component',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.sin(Math.PI / 2 - Math.atan(height / width)),
            directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI + 180,
            component: true,
        };
        const gravityPerpendicular: IForce = {
            description: 'Gravity Perpendicular Component',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(Math.PI / 2 - Math.atan(height / width)),
            directionInDegrees: 360 - (Math.atan(height / width) * 180) / Math.PI,
            component: true,
        };
        const gravityForce: IForce = {
            description: 'Gravity',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
            directionInDegrees: 270,
            component: false,
        };
        if (coefficient != 0) {
            this.dataDoc.start_Forces = [gravityForce, normalForce, frictionForce];
            this.dataDoc.updatedForces = [gravityForce, normalForce, frictionForce];
            this.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
        } else {
            this.dataDoc.start_Forces = [gravityForce, normalForce];
            this.dataDoc.updatedForces = [gravityForce, normalForce];
            this.dataDoc.componentForces = [normalForceComponent, gravityParallel, gravityPerpendicular];
        }
    };

    // Change wedge height and width and weight position to match new wedge angle
    changeWedgeBasedOnNewAngle = (angle: number) => {
        this.dataDoc.wedgeWidth = this.xMax * 0.5;
        this.dataDoc.wedgeHeight = Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5;

        // update weight position based on updated wedge width/height
        let yPos = this.yMax - 0.08 * this.layoutDoc[HeightSym]() * 2 - Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5;

        // adjust y position
        if (angle >= 5 && angle < 10) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.1;
        } else if (angle >= 10 && angle < 15) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.23;
        } else if (angle >= 15 && angle < 20) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.26;
        } else if (angle >= 20 && angle < 25) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.33;
        } else if (angle >= 25 && angle < 30) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.35;
        } else if (angle >= 30 && angle < 35) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.4;
        } else if (angle >= 35 && angle < 40) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.45;
        } else if (angle >= 40 && angle < 45) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.47;
        } else if (angle >= 45) {
            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.52;
        }

        this.dataDoc.start_PosX = this.xMax * 0.25;
        this.dataDoc.start_PosY = yPos;
        if (this.dataDoc.mode == 'Freeform') {
            this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction), this.xMax * 0.5, Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5);
        }
    };

    // In review mode, update forces when coefficient of static friction changed
    updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
        let theta: number = NumCast(this.dataDoc.wedgeAngle);
        let index = this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45');
        if (index >= 0) {
            theta = NumListCast(this.dataDoc.questionVariables)[index];
        }
        if (isNaN(theta)) {
            return;
        }
        this.dataDoc.review_GravityMagnitude = Math.abs(NumCast(this.dataDoc.gravity));
        this.dataDoc.review_GravityAngle = 270;
        this.dataDoc.review_NormalMagnitude = Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta * Math.PI) / 180);
        this.dataDoc.review_NormalAngle = 90 - theta;
        let yForce = -Math.abs(NumCast(this.dataDoc.gravity));
        yForce += Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta * Math.PI) / 180) * Math.sin(((90 - theta) * Math.PI) / 180);
        yForce += coefficient * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta * Math.PI) / 180) * Math.sin(((180 - theta) * Math.PI) / 180);
        let friction = coefficient * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta * Math.PI) / 180);
        if (yForce > 0) {
            friction = (-(Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta * Math.PI) / 180)) * Math.sin(((90 - theta) * Math.PI) / 180) + Math.abs(NumCast(this.dataDoc.gravity))) / Math.sin(((180 - theta) * Math.PI) / 180);
        }
        this.dataDoc.review_StaticMagnitude = friction;
        this.dataDoc.review_StaticAngle = 180 - theta;
    };

    // In review mode, update forces when wedge angle changed
    updateReviewForcesBasedOnAngle = (angle: number) => {
        this.dataDoc.review_GravityMagnitude = Math.abs(NumCast(this.dataDoc.gravity));
        this.dataDoc.review_GravityAngle = 270;
        this.dataDoc.review_NormalMagnitude = Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((angle * Math.PI) / 180);
        this.dataDoc.review_NormalAngle = 90 - angle;
        let yForce = -Math.abs(NumCast(this.dataDoc.gravity));
        yForce += Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((angle * Math.PI) / 180) * Math.sin(((90 - angle) * Math.PI) / 180);
        yForce += NumCast(this.dataDoc.review_Coefficient) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((angle * Math.PI) / 180) * Math.sin(((180 - angle) * Math.PI) / 180);
        let friction = NumCast(this.dataDoc.review_Coefficient) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((angle * Math.PI) / 180);
        if (yForce > 0) {
            friction = (-(Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((angle * Math.PI) / 180)) * Math.sin(((90 - angle) * Math.PI) / 180) + Math.abs(NumCast(this.dataDoc.gravity))) / Math.sin(((180 - angle) * Math.PI) / 180);
        }
        this.dataDoc.review_StaticMagnitude = friction;
        this.dataDoc.review_StaticAngle = 180 - angle;
    };

    // Solve for the correct answers to the generated problem
    getAnswersToQuestion = (question: QuestionTemplate, questionVars: number[]) => {
        const solutions: number[] = [];

        let theta: number = NumCast(this.dataDoc.wedgeAngle);
        let index = question.variablesForQuestionSetup.indexOf('theta - max 45');
        if (index >= 0) {
            theta = questionVars[index];
        }
        let muS: number = NumCast(this.dataDoc.coefficientOfStaticFriction);
        index = question.variablesForQuestionSetup.indexOf('coefficient of static friction');
        if (index >= 0) {
            muS = questionVars[index];
        }

        for (let i = 0; i < question.answerSolutionDescriptions.length; i++) {
            const description = question.answerSolutionDescriptions[i];
            if (!isNaN(NumCast(description))) {
                solutions.push(NumCast(description));
            } else if (description == 'solve normal force angle from wedge angle') {
                solutions.push(90 - theta);
            } else if (description == 'solve normal force magnitude from wedge angle') {
                solutions.push(Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta / 180) * Math.PI));
            } else if (description == 'solve static force magnitude from wedge angle given equilibrium') {
                let normalForceMagnitude = Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta / 180) * Math.PI);
                let normalForceAngle = 90 - theta;
                let frictionForceAngle = 180 - theta;
                let frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(NumCast(this.dataDoc.gravity))) / Math.sin((frictionForceAngle * Math.PI) / 180);
                solutions.push(frictionForceMagnitude);
            } else if (description == 'solve static force angle from wedge angle given equilibrium') {
                solutions.push(180 - theta);
            } else if (description == 'solve minimum static coefficient from wedge angle given equilibrium') {
                let normalForceMagnitude = Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((theta / 180) * Math.PI);
                let normalForceAngle = 90 - theta;
                let frictionForceAngle = 180 - theta;
                let frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(NumCast(this.dataDoc.gravity))) / Math.sin((frictionForceAngle * Math.PI) / 180);
                let frictionCoefficient = frictionForceMagnitude / normalForceMagnitude;
                solutions.push(frictionCoefficient);
            } else if (description == 'solve maximum wedge angle from coefficient of static friction given equilibrium') {
                solutions.push((Math.atan(muS) * 180) / Math.PI);
            }
        }
        this.dataDoc.selectedSolutions = solutions;
        return solutions;
    };

    // In review mode, check if input answers match correct answers and optionally generate alert
    checkAnswers = (showAlert: boolean = true) => {
        let error: boolean = false;
        let epsilon: number = 0.01;
        if (this.dataDoc.selectedQuestion) {
            for (let i = 0; i < this.dataDoc.selectedQuestion.answerParts.length; i++) {
                if (this.dataDoc.selectedQuestion.answerParts[i] == 'force of gravity') {
                    if (Math.abs(NumCast(this.dataDoc.review_GravityMagnitude) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'angle of gravity') {
                    if (Math.abs(NumCast(this.dataDoc.review_GravityAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'normal force') {
                    if (Math.abs(NumCast(this.dataDoc.review_NormalMagnitude) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'angle of normal force') {
                    if (Math.abs(NumCast(this.dataDoc.review_NormalAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'force of static friction') {
                    if (Math.abs(NumCast(this.dataDoc.review_StaticMagnitude) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'angle of static friction') {
                    if (Math.abs(NumCast(this.dataDoc.review_StaticAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'coefficient of static friction') {
                    if (Math.abs(NumCast(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'wedge angle') {
                    if (Math.abs(NumCast(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                        error = true;
                    }
                }
            }
        }
        if (showAlert) {
            if (!error) {
                this.dataDoc.simulation_Paused = false;
                setTimeout(() => {
                    this.dataDoc.simulation_Paused = true;
                }, 3000);
            } else {
                this.dataDoc.simulation_Paused = false;
                setTimeout(() => {
                    this.dataDoc.simulation_Paused = true;
                }, 3000);
            }
        }
        if (this.dataDoc.selectedQuestion.goal == 'noMovement') {
            if (!error) {
                this.dataDoc.noMovement = true;
            } else {
                this.dataDoc.roMovement = false;
            }
        }
    };

    // Reset all review values to default
    resetReviewValuesToDefault = () => {
        this.dataDoc.review_GravityMagnitude = 0;
        this.dataDoc.review_GravityAngle = 0;
        this.dataDoc.review_NormalMagnitude = 0;
        this.dataDoc.review_NormalAngle = 0;
        this.dataDoc.review_StaticMagnitude = 0;
        this.dataDoc.review_StaticAngle = 0;
        this.dataDoc.coefficientOfKineticFriction = 0;
        this.dataDoc.simulation_Paused = true;
    };

    // In review mode, reset problem variables and generate a new question
    generateNewQuestion = () => {
        this.resetReviewValuesToDefault();

        const vars: number[] = [];
        let question: QuestionTemplate = questions.inclinePlane[0];

        if (this.dataDoc.simulation_Type == 'Inclined Plane') {
            if (this.dataDoc.questionNumber === questions.inclinePlane.length - 1) {
                this.dataDoc.questionNumber = 0;
            } else {
                this.dataDoc.questionNumber = NumCast(this.dataDoc.questionNumber) + 1;
            }
            question = questions.inclinePlane[NumCast(this.dataDoc.questionNumber)];

            let coefficient = 0;
            let wedgeAngle = 0;

            for (let i = 0; i < question.variablesForQuestionSetup.length; i++) {
                if (question.variablesForQuestionSetup[i] == 'theta - max 45') {
                    let randValue = Math.floor(Math.random() * 44 + 1);
                    vars.push(randValue);
                    wedgeAngle = randValue;
                } else if (question.variablesForQuestionSetup[i] == 'coefficient of static friction') {
                    let randValue = Math.round(Math.random() * 1000) / 1000;
                    vars.push(randValue);
                    coefficient = randValue;
                }
            }
            this.dataDoc.wedgeAngle = wedgeAngle;
            this.changeWedgeBasedOnNewAngle(wedgeAngle);
            this.dataDoc.coefficientOfStaticFriction = coefficient;
            this.dataDoc.review_Coefficient = coefficient;
        }
        let q = '';
        for (let i = 0; i < question.questionSetup.length; i++) {
            q += question.questionSetup[i];
            if (i != question.questionSetup.length - 1) {
                q += vars[i];
                if (question.variablesForQuestionSetup[i].includes('theta')) {
                    q += ' degree (≈' + Math.round((1000 * (vars[i] * Math.PI)) / 180) / 1000 + ' rad)';
                }
            }
        }
        this.dataDoc.questionVariables = new List<number>(vars);
        this.dataDoc.selectedQuestion = question;
        this.dataDoc.questionPartOne = q;
        this.dataDoc.questionPartTwo = question.question;
        this.dataDoc.answers = new List<number>(this.getAnswersToQuestion(question, vars));
        //this.dataDoc.simulation_Reset = (!this.dataDoc.simulation_Reset);
    };

    // Default setup for uniform circular motion simulation
    setupCircular = (value: number) => {
        this.dataDoc.show_ComponentForces = false;
        this.dataDoc.start_VelY = 0;
        this.dataDoc.start_VelX = value;
        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
        let yPos = (this.yMax + this.yMin) / 2 + NumCast(this.dataDoc.circularMotionRadius) - 0.08 * this.layoutDoc[HeightSym]();
        this.dataDoc.start_PosY = yPos;
        this.dataDoc.start_PosX = xPos;
        const tensionForce: IForce = {
            description: 'Centripetal Force',
            magnitude: (this.dataDoc.start_VelX ** 2 * NumCast(this.dataDoc.mass)) / NumCast(this.dataDoc.circularMotionRadius),
            directionInDegrees: 90,
            component: false,
        };
        this.dataDoc.updatedForces = [tensionForce];
        this.dataDoc.start_Forces = [tensionForce];
        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
    };

    // Default setup for pendulum simulation
    setupPendulum = () => {
        const length = 300;
        const angle = 30;
        const x = length * Math.cos(((90 - angle) * Math.PI) / 180);
        const y = length * Math.sin(((90 - angle) * Math.PI) / 180);
        const xPos = this.xMax / 2 - x - 0.08 * this.layoutDoc[HeightSym]();
        const yPos = y - 0.08 * this.layoutDoc[HeightSym]() - 5;
        this.dataDoc.start_PosX = xPos;
        this.dataDoc.start_PosY = yPos;
        const mag = NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.sin((60 * Math.PI) / 180);
        const forceOfTension: IForce = {
            description: 'Tension',
            magnitude: mag,
            directionInDegrees: 90 - angle,
            component: false,
        };

        const tensionComponent: IForce = {
            description: 'Tension',
            magnitude: mag,
            directionInDegrees: 90 - angle,
            component: true,
        };
        const gravityParallel: IForce = {
            description: 'Gravity Parallel Component',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.sin(((90 - angle) * Math.PI) / 180),
            directionInDegrees: -angle - 90,
            component: true,
        };
        const gravityPerpendicular: IForce = {
            description: 'Gravity Perpendicular Component',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(((90 - angle) * Math.PI) / 180),
            directionInDegrees: -angle,
            component: true,
        };

        this.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
        this.dataDoc.updatedForces = [
            {
                description: 'Gravity',
                magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                directionInDegrees: 270,
                component: false,
            },
            forceOfTension,
        ];
        this.dataDoc.start_Forces = [
            {
                description: 'Gravity',
                magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                directionInDegrees: 270,
                component: false,
            },
            forceOfTension,
        ];
        this.dataDoc.start_PendulumAngle = 30;
        this.dataDoc.pendulum_angle = 30;
        this.dataDoc.pendulum_length = 300;
        this.dataDoc.pendulum_angle_adjust = 30;
        this.dataDoc.pendulum_length_adjust = 300;
    };

    // Default setup for spring simulation
    setupSpring = () => {
        this.dataDoc.show_ComponentForces = false;
        const gravityForce: IForce = {
            description: 'Gravity',
            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
            directionInDegrees: 270,
            component: false,
        };
        this.dataDoc.updatedForces = [gravityForce];
        this.dataDoc.start_Forces = [gravityForce];
        this.dataDoc.start_PosX = this.xMax / 2 - 0.08 * this.layoutDoc[HeightSym]();
        this.dataDoc.start_PosY = 200;
        this.dataDoc.springConstant = 0.5;
        this.dataDoc.springRestLength = 200;
        this.dataDoc.springStartLength = 200;
        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
    };

    // Default setup for suspension simulation
    setupSuspension = () => {
        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
        let yPos = this.yMin + 200;
        this.dataDoc.start_PosY = yPos;
        this.dataDoc.start_PosX = xPos;
        this.dataDoc.position_YDisplay = this.getDisplayYPos(yPos);
        this.dataDoc.position_XDisplay = xPos;
        let tensionMag = (NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity))) / (2 * Math.sin(Math.PI / 4));
        const tensionForce1: IForce = {
            description: 'Tension',
            magnitude: tensionMag,
            directionInDegrees: 45,
            component: false,
        };
        const tensionForce2: IForce = {
            description: 'Tension',
            magnitude: tensionMag,
            directionInDegrees: 135,
            component: false,
        };
        const grav: IForce = {
            description: 'Gravity',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
            directionInDegrees: 270,
            component: false,
        };
        this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
        this.dataDoc.start_Forces = [tensionForce1, tensionForce2, grav];
        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
    };

    // Default setup for pulley simulation
    setupPulley = () => {
        this.dataDoc.show_ComponentForces = false;
        this.dataDoc.start_PosY = (this.yMax + this.yMin) / 2;
        this.dataDoc.start_PosX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
        this.dataDoc.position_YDisplay = this.getDisplayYPos((this.yMax + this.yMin) / 2);
        this.dataDoc.position_XDisplay = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
        let a = (-1 * ((NumCast(this.dataDoc.mass) - NumCast(this.dataDoc.mass2)) * Math.abs(NumCast(this.dataDoc.gravity)))) / (NumCast(this.dataDoc.mass) + NumCast(this.dataDoc.mass2));
        const gravityForce1: IForce = {
            description: 'Gravity',
            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
            directionInDegrees: 270,
            component: false,
        };
        const tensionForce1: IForce = {
            description: 'Tension',
            magnitude: NumCast(this.dataDoc.mass) * a + NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
            directionInDegrees: 90,
            component: false,
        };
        a *= -1;
        const gravityForce2: IForce = {
            description: 'Gravity',
            magnitude: NumCast(this.dataDoc.mass2) * Math.abs(NumCast(this.dataDoc.gravity)),
            directionInDegrees: 270,
            component: false,
        };
        const tensionForce2: IForce = {
            description: 'Tension',
            magnitude: NumCast(this.dataDoc.mass2) * a + NumCast(this.dataDoc.mass2) * Math.abs(NumCast(this.dataDoc.gravity)),
            directionInDegrees: 90,
            component: false,
        };

        this.dataDoc.updatedForces = [gravityForce1, tensionForce1];
        this.dataDoc.start_Forces = [gravityForce1, tensionForce1];
        this.dataDoc.start_PosY2 = (this.yMax + this.yMin) / 2;
        this.dataDoc.start_PosX2 = (this.xMin + this.xMax) / 2 + 5;
        this.dataDoc.position_YDisplay2 = this.getDisplayYPos((this.yMax + this.yMin) / 2);
        this.dataDoc.position_XDisplay2 = (this.xMin + this.xMax) / 2 + 5;
        this.dataDoc.updatedForces2 = [gravityForce2, tensionForce2];
        this.dataDoc.start_Forces2 = [gravityForce2, tensionForce2];

        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
    };

    // Helper function used for tutorial and review mode
    getForceFromJSON = (
        json: {
            description: string;
            magnitude: number;
            directionInDegrees: number;
            component: boolean;
        }[]
    ): IForce[] => {
        const forces: IForce[] = [];
        for (let i = 0; i < json.length; i++) {
            const force: IForce = {
                description: json[i].description,
                magnitude: json[i].magnitude,
                directionInDegrees: json[i].directionInDegrees,
                component: json[i].component,
            };
            forces.push(force);
        }
        return forces;
    };

    // Handle force change in review mode
    updateReviewModeValues = () => {
        const forceOfGravityReview: IForce = {
            description: 'Gravity',
            magnitude: NumCast(this.dataDoc.review_GravityMagnitude),
            directionInDegrees: NumCast(this.dataDoc.review_GravityAngle),
            component: false,
        };
        const normalForceReview: IForce = {
            description: 'Normal Force',
            magnitude: NumCast(this.dataDoc.review_NormalMagnitude),
            directionInDegrees: NumCast(this.dataDoc.review_NormalAngle),
            component: false,
        };
        const staticFrictionForceReview: IForce = {
            description: 'Static Friction Force',
            magnitude: NumCast(this.dataDoc.review_StaticMagnitude),
            directionInDegrees: NumCast(this.dataDoc.review_StaticAngle),
            component: false,
        };
        this.dataDoc.start_Forces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
        this.dataDoc.updatedForces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
    };

    render() {
        return (
            <div className="physicsSimApp">
                <div className="mechanicsSimulationContainer">
                    <div className="mechanicsSimulationContentContainer">
                        <div className="mechanicsSimulationButtonsAndElements">
                            <div className="mechanicsSimulationButtons">
                                {!this.dataDoc.simulation_Paused && (
                                    <div
                                        style={{
                                            position: 'fixed',
                                            left: 0.1 * this.layoutDoc[WidthSym]() + 'px',
                                            top: 0.95 * this.layoutDoc[HeightSym]() + 'px',
                                            width: 0.5 * this.layoutDoc[WidthSym]() + 'px',
                                        }}>
                                        <LinearProgress />
                                    </div>
                                )}
                            </div>
                            <div className="mechanicsSimulationElements">
                                <Weight
                                    dataDoc={this.dataDoc}
                                    layoutDoc={this.layoutDoc}
                                    wallPositions={this.wallPositions}
                                    adjustPendulumAngle={NumCast(this.dataDoc.pendulum_angle_adjust)}
                                    adjustPendulumLength={NumCast(this.dataDoc.pendulum_length_adjust)}
                                    gravity={NumCast(this.dataDoc.gravity)}
                                    circularMotionRadius={NumCast(this.dataDoc.circularMotionRadius)}
                                    componentForces={this.dataDoc.componentForces}
                                    showComponentForces={BoolCast(this.dataDoc.show_ComponentForces)}
                                    color={'red'}
                                    coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
                                    displayXVelocity={NumCast(this.dataDoc.velocity_XDisplay)}
                                    displayYVelocity={NumCast(this.dataDoc.velocity_YDisplay)}
                                    elasticCollisions={BoolCast(this.dataDoc.elasticCollisions)}
                                    mass={NumCast(this.dataDoc.mass)}
                                    mode={StrCast(this.dataDoc.mode)}
                                    noMovement={BoolCast(this.dataDoc.noMovement)}
                                    paused={BoolCast(this.dataDoc.simulation_Paused)}
                                    pendulumAngle={NumCast(this.dataDoc.pendulum_angle)}
                                    pendulumLength={NumCast(this.dataDoc.pendulum_length)}
                                    radius={0.08 * this.layoutDoc[HeightSym]()}
                                    reset={BoolCast(this.dataDoc.simulation_Reset)}
                                    simulationSpeed={NumCast(this.dataDoc.simulation_Speed)}
                                    startPendulumAngle={NumCast(this.dataDoc.start_PendulumAngle)}
                                    showAcceleration={BoolCast(this.dataDoc.show_Acceleration)}
                                    showForceMagnitudes={BoolCast(this.dataDoc.show_ForceMagnitudes)}
                                    showForces={BoolCast(this.dataDoc.show_Forces)}
                                    showVelocity={BoolCast(this.dataDoc.show_Velocity)}
                                    simulationType={StrCast(this.dataDoc.simulation_Type)}
                                    springConstant={NumCast(this.dataDoc.springConstant)}
                                    springStartLength={NumCast(this.dataDoc.springStartLength)}
                                    springRestLength={NumCast(this.dataDoc.springRestLength)}
                                    startForces={this.dataDoc.start_Forces}
                                    startPosX={NumCast(this.dataDoc.start_PosX)}
                                    startPosY={NumCast(this.dataDoc.start_PosY)}
                                    startVelX={NumCast(this.dataDoc.start_VelX)}
                                    startVelY={NumCast(this.dataDoc.start_VelY)}
                                    timestepSize={0.05}
                                    updateXDisplay={NumCast(this.dataDoc.display_xChange)}
                                    updateYDisplay={NumCast(this.dataDoc.display_yChange)}
                                    updatedForces={this.dataDoc.updatedForces}
                                    wedgeHeight={NumCast(this.dataDoc.wedgeHeight)}
                                    wedgeWidth={NumCast(this.dataDoc.wedgeWidth)}
                                    xMax={this.xMax}
                                    xMin={this.xMin}
                                    yMax={this.yMax}
                                    yMin={this.yMin}
                                />
                                {this.dataDoc.simulation_Type == 'Pulley' && (
                                    <Weight
                                        dataDoc={this.dataDoc}
                                        layoutDoc={this.layoutDoc}
                                        wallPositions={this.wallPositions}
                                        adjustPendulumAngle={NumCast(this.dataDoc.pendulum_angle_adjust)}
                                        adjustPendulumLength={NumCast(this.dataDoc.pendulum_length_adjust)}
                                        circularMotionRadius={NumCast(this.dataDoc.circularMotionRadius)}
                                        gravity={NumCast(this.dataDoc.gravity)}
                                        componentForces={this.dataDoc.componentForces}
                                        showComponentForces={BoolCast(this.dataDoc.show_ComponentForces)}
                                        color={'blue'}
                                        coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
                                        displayXVelocity={NumCast(this.dataDoc.velocity_XDisplay)}
                                        displayYVelocity={NumCast(this.dataDoc.velocity_YDisplay)}
                                        elasticCollisions={BoolCast(this.dataDoc.elasticCollisions)}
                                        mass={NumCast(this.dataDoc.mass2)}
                                        mode={StrCast(this.dataDoc.mode)}
                                        noMovement={BoolCast(this.dataDoc.noMovement)}
                                        paused={BoolCast(this.dataDoc.simulation_Paused)}
                                        pendulumAngle={NumCast(this.dataDoc.pendulum_angle)}
                                        pendulumLength={NumCast(this.dataDoc.pendulum_length)}
                                        radius={0.08 * this.layoutDoc[HeightSym]()}
                                        reset={BoolCast(this.dataDoc.simulation_Reset)}
                                        simulationSpeed={NumCast(this.dataDoc.simulation_Speed)}
                                        startPendulumAngle={NumCast(this.dataDoc.start_PendulumAngle)}
                                        showAcceleration={BoolCast(this.dataDoc.show_Acceleration)}
                                        showForceMagnitudes={BoolCast(this.dataDoc.show_ForceMagnitudes)}
                                        showForces={BoolCast(this.dataDoc.show_Forces)}
                                        showVelocity={BoolCast(this.dataDoc.show_Velocity)}
                                        simulationType={this.dataDoc.simulation_Type}
                                        springConstant={NumCast(this.dataDoc.springConstant)}
                                        springStartLength={NumCast(this.dataDoc.springStartLength)}
                                        springRestLength={NumCast(this.dataDoc.springRestLength)}
                                        startForces={this.dataDoc.start_Forces2}
                                        startPosX={NumCast(this.dataDoc.start_PosX2)}
                                        startPosY={NumCast(this.dataDoc.start_PosY2)}
                                        startVelX={NumCast(this.dataDoc.start_VelX)}
                                        startVelY={NumCast(this.dataDoc.start_VelY)}
                                        timestepSize={0.05}
                                        updateXDisplay={NumCast(this.dataDoc.display_xChange2)}
                                        updateYDisplay={NumCast(this.dataDoc.display_yChange2)}
                                        updatedForces={this.dataDoc.updatedForces2}
                                        wedgeHeight={NumCast(this.dataDoc.wedgeHeight)}
                                        wedgeWidth={NumCast(this.dataDoc.wedgeWidth)}
                                        xMax={this.xMax}
                                        xMin={this.xMin}
                                        yMax={this.yMax}
                                        yMin={this.yMin}
                                    />
                                )}
                            </div>
                            <div>
                                {(this.dataDoc.simulation_Type == 'One Weight' || this.dataDoc.simulation_Type == 'Inclined Plane') &&
                                    this.wallPositions &&
                                    this.wallPositions.map((element, index) => {
                                        return <Wall key={index} length={element.length} xPos={element.xPos} yPos={element.yPos} angleInDegrees={element.angleInDegrees} />;
                                    })}
                            </div>
                        </div>
                    </div>
                    <div className="mechanicsSimulationEquationContainer">
                        <div className="mechanicsSimulationControls">
                            <Stack direction="row" spacing={1}>
                                {this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
                                    <IconButton
                                        onClick={() => {
                                            this.dataDoc.simulation_Paused = false;
                                        }}>
                                        <PlayArrowIcon />
                                    </IconButton>
                                )}
                                {!this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
                                    <IconButton
                                        onClick={() => {
                                            this.dataDoc.simulation_Paused = true;
                                        }}>
                                        <PauseIcon />
                                    </IconButton>
                                )}
                                {this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
                                    <IconButton
                                        onClick={() => {
                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                        }}>
                                        <ReplayIcon />
                                    </IconButton>
                                )}
                            </Stack>
                            <div className="dropdownMenu">
                                <select
                                    value={StrCast(this.dataDoc.simulation_Type)}
                                    onChange={event => {
                                        this.dataDoc.simulation_Type = event.target.value;
                                        this.setupSimulation(event.target.value, StrCast(this.dataDoc.mode));
                                    }}
                                    style={{ height: '2em', width: '100%', fontSize: '16px' }}>
                                    <option value="One Weight">Projectile</option>
                                    <option value="Inclined Plane">Inclined Plane</option>
                                    <option value="Pendulum">Pendulum</option>
                                    <option value="Spring">Spring</option>
                                    <option value="Circular Motion">Circular Motion</option>
                                    <option value="Pulley">Pulley</option>
                                    <option value="Suspension">Suspension</option>
                                </select>
                            </div>
                            <div className="dropdownMenu">
                                <select
                                    value={StrCast(this.dataDoc.mode)}
                                    onChange={event => {
                                        this.dataDoc.mode = event.target.value;
                                        this.setupSimulation(StrCast(this.dataDoc.simulation_Type), event.target.value);
                                    }}
                                    style={{ height: '2em', width: '100%', fontSize: '16px' }}>
                                    <option value="Tutorial">Tutorial Mode</option>
                                    <option value="Freeform">Freeform Mode</option>
                                    <option value="Review">Review Mode</option>
                                </select>
                            </div>
                        </div>
                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type != 'Inclined Plane' && (
                            <div className="wordProblemBox">
                                <p>{this.dataDoc.simulation_Type} review problems in progress!</p>
                                <hr />
                            </div>
                        )}
                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type == 'Inclined Plane' && (
                            <div>
                                {!this.dataDoc.hintDialogueOpen && (
                                    <IconButton
                                        onClick={() => {
                                            this.dataDoc.hintDialogueOpen = true;
                                        }}
                                        sx={{
                                            position: 'fixed',
                                            left: this.xMax - 50 + 'px',
                                            top: this.yMin + 14 + 'px',
                                        }}>
                                        <QuestionMarkIcon />
                                    </IconButton>
                                )}
                                <Dialog maxWidth={'sm'} fullWidth={true} open={BoolCast(this.dataDoc.hintDialogueOpen)} onClose={() => (this.dataDoc.hintDialogueOpen = false)}>
                                    <DialogTitle>Hints</DialogTitle>
                                    <DialogContent>
                                        {this.dataDoc.selectedQuestion.hints?.map((hint: any, index: number) => {
                                            return (
                                                <div key={index}>
                                                    <DialogContentText>
                                                        <details>
                                                            <summary>
                                                                <b>
                                                                    Hint {index + 1}: {hint.description}
                                                                </b>
                                                            </summary>
                                                            {hint.content}
                                                        </details>
                                                    </DialogContentText>
                                                </div>
                                            );
                                        })}
                                    </DialogContent>
                                    <DialogActions>
                                        <Button
                                            onClick={() => {
                                                this.dataDoc.hintDialogueOpen = false;
                                            }}>
                                            Close
                                        </Button>
                                    </DialogActions>
                                </Dialog>
                                <div className="wordProblemBox">
                                    <div className="question">
                                        <p>{StrCast(this.dataDoc.questionPartOne)}</p>
                                        <p>{StrCast(this.dataDoc.questionPartTwo)}</p>
                                    </div>
                                    <div className="answers">
                                        {this.dataDoc.selectedQuestion.answerParts.includes('force of gravity') && (
                                            <InputField
                                                label={<p>Gravity magnitude</p>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="review_GravityMagnitude"
                                                step={0.1}
                                                unit={'N'}
                                                upperBound={50}
                                                value={NumCast(this.dataDoc.review_GravityMagnitude)}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('force of gravity')]}
                                                labelWidth={'7em'}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('angle of gravity') && (
                                            <InputField
                                                label={<p>Gravity angle</p>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="review_GravityAngle"
                                                step={1}
                                                unit={'°'}
                                                upperBound={360}
                                                value={NumCast(this.dataDoc.review_GravityAngle)}
                                                radianEquivalent={true}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of gravity')]}
                                                labelWidth={'7em'}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('normal force') && (
                                            <InputField
                                                label={<p>Normal force magnitude</p>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="review_NormalMagnitude"
                                                step={0.1}
                                                unit={'N'}
                                                upperBound={50}
                                                value={NumCast(this.dataDoc.review_NormalMagnitude)}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('normal force')]}
                                                labelWidth={'7em'}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('angle of normal force') && (
                                            <InputField
                                                label={<p>Normal force angle</p>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="review_NormalAngle"
                                                step={1}
                                                unit={'°'}
                                                upperBound={360}
                                                value={NumCast(this.dataDoc.review_NormalAngle)}
                                                radianEquivalent={true}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of normal force')]}
                                                labelWidth={'7em'}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('force of static friction') && (
                                            <InputField
                                                label={<p>Static friction magnitude</p>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="review_StaticMagnitude"
                                                step={0.1}
                                                unit={'N'}
                                                upperBound={50}
                                                value={NumCast(this.dataDoc.review_StaticMagnitude)}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('force of static friction')]}
                                                labelWidth={'7em'}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('angle of static friction') && (
                                            <InputField
                                                label={<p>Static friction angle</p>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="review_StaticAngle"
                                                step={1}
                                                unit={'°'}
                                                upperBound={360}
                                                value={NumCast(this.dataDoc.review_StaticAngle)}
                                                radianEquivalent={true}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of static friction')]}
                                                labelWidth={'7em'}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('coefficient of static friction') && (
                                            <InputField
                                                label={
                                                    <Box>
                                                        &mu;<sub>s</sub>
                                                    </Box>
                                                }
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="coefficientOfStaticFriction"
                                                step={0.1}
                                                unit={''}
                                                upperBound={1}
                                                value={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                                effect={this.updateReviewForcesBasedOnCoefficient}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('coefficient of static friction')]}
                                            />
                                        )}
                                        {this.dataDoc.selectedQuestion.answerParts.includes('wedge angle') && (
                                            <InputField
                                                label={<Box>&theta;</Box>}
                                                lowerBound={0}
                                                dataDoc={this.dataDoc}
                                                prop="wedgeAngle"
                                                step={1}
                                                unit={'°'}
                                                upperBound={49}
                                                value={NumCast(this.dataDoc.wedgeAngle, 26)}
                                                effect={(val: number) => {
                                                    this.changeWedgeBasedOnNewAngle(val);
                                                    this.updateReviewForcesBasedOnAngle(val);
                                                }}
                                                radianEquivalent={true}
                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('wedge angle')]}
                                            />
                                        )}
                                    </div>
                                </div>
                            </div>
                        )}
                        {this.dataDoc.mode == 'Tutorial' && (
                            <div className="wordProblemBox">
                                <div className="question">
                                    <h2>Problem</h2>
                                    <p>{this.dataDoc.selectedTutorial.question}</p>
                                </div>
                                <div
                                    style={{
                                        display: 'flex',
                                        justifyContent: 'spaceBetween',
                                        width: '100%',
                                    }}>
                                    <IconButton
                                        onClick={() => {
                                            let step = NumCast(this.dataDoc.stepNumber) - 1;
                                            step = Math.max(step, 0);
                                            step = Math.min(step, this.dataDoc.selectedTutorial.steps.length - 1);
                                            this.dataDoc.stepNumber = step;
                                            this.dataDoc.start_Forces = this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces);
                                            this.dataDoc.updatedForces = this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces);
                                            this.dataDoc.show_ForceMagnitudes = this.dataDoc.selectedTutorial.steps[step].show_Magnitude;
                                        }}
                                        disabled={this.dataDoc.stepNumber == 0}>
                                        <ArrowLeftIcon />
                                    </IconButton>
                                    <div>
                                        <h3>
                                            Step {NumCast(this.dataDoc.stepNumber) + 1}: {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
                                        </h3>
                                        <p>{this.dataDoc.selectedTutorial.steps[NumCast(this.dataDoc.stepNumber)].content}</p>
                                    </div>
                                    <IconButton
                                        onClick={() => {
                                            let step = NumCast(this.dataDoc.stepNumber) + 1;
                                            step = Math.max(step, 0);
                                            step = Math.min(step, this.dataDoc.selectedTutorial.steps.length - 1);
                                            this.dataDoc.stepNumber = step;
                                            this.dataDoc.start_Forces = this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces);
                                            this.dataDoc.updatedForces = this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces);
                                            this.dataDoc.show_ForceMagnitudes = this.dataDoc.selectedTutorial.steps[step].show_Magnitude;
                                        }}
                                        disabled={this.dataDoc.stepNumber == this.dataDoc.selectedTutorial.steps.length - 1}>
                                        <ArrowRightIcon />
                                    </IconButton>
                                </div>
                                <div>
                                    {(this.dataDoc.simulation_Type == 'One Weight' || this.dataDoc.simulation_Type == 'Inclined Plane' || this.dataDoc.simulation_Type == 'Pendulum') && <p>Resources</p>}
                                    {this.dataDoc.simulation_Type == 'One Weight' && (
                                        <ul>
                                            <li>
                                                <a
                                                    href="https://www.khanacademy.org/science/physics/one-dimensional-motion"
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    style={{
                                                        color: 'blue',
                                                        textDecoration: 'underline',
                                                    }}>
                                                    Khan Academy - One Dimensional Motion
                                                </a>
                                            </li>
                                            <li>
                                                <a
                                                    href="https://www.khanacademy.org/science/physics/two-dimensional-motion"
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    style={{
                                                        color: 'blue',
                                                        textDecoration: 'underline',
                                                    }}>
                                                    Khan Academy - Two Dimensional Motion
                                                </a>
                                            </li>
                                        </ul>
                                    )}
                                    {this.dataDoc.simulation_Type == 'Inclined Plane' && (
                                        <ul>
                                            <li>
                                                <a
                                                    href="https://www.khanacademy.org/science/physics/forces-newtons-laws#normal-contact-force"
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    style={{
                                                        color: 'blue',
                                                        textDecoration: 'underline',
                                                    }}>
                                                    Khan Academy - Normal Force
                                                </a>
                                            </li>
                                            <li>
                                                <a
                                                    href="https://www.khanacademy.org/science/physics/forces-newtons-laws#inclined-planes-friction"
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    style={{
                                                        color: 'blue',
                                                        textDecoration: 'underline',
                                                    }}>
                                                    Khan Academy - Inclined Planes
                                                </a>
                                            </li>
                                        </ul>
                                    )}
                                    {this.dataDoc.simulation_Type == 'Pendulum' && (
                                        <ul>
                                            <li>
                                                <a
                                                    href="https://www.khanacademy.org/science/physics/forces-newtons-laws#tension-tutorial"
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    style={{
                                                        color: 'blue',
                                                        textDecoration: 'underline',
                                                    }}>
                                                    Khan Academy - Tension
                                                </a>
                                            </li>
                                        </ul>
                                    )}
                                </div>
                            </div>
                        )}
                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type == 'Inclined Plane' && (
                            <div
                                style={{
                                    display: 'flex',
                                    justifyContent: 'space-between',
                                    marginTop: '10px',
                                }}>
                                <p
                                    style={{
                                        color: 'blue',
                                        textDecoration: 'underline',
                                        cursor: 'pointer',
                                    }}
                                    onClick={() => (this.dataDoc.mode = 'Tutorial')}>
                                    {' '}
                                    Go to walkthrough{' '}
                                </p>
                                <div style={{ display: 'flex', flexDirection: 'column' }}>
                                    <Button
                                        onClick={() => {
                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            this.checkAnswers();
                                            this.dataDoc.show_Icon = true;
                                        }}
                                        variant="outlined">
                                        <p>Submit</p>
                                    </Button>
                                    <Button
                                        onClick={() => {
                                            this.generateNewQuestion();
                                            this.dataDoc.show_Icon = false;
                                        }}
                                        variant="outlined">
                                        <p>New question</p>
                                    </Button>
                                </div>
                            </div>
                        )}
                        {this.dataDoc.mode == 'Freeform' && (
                            <div className="vars">
                                <FormControl component="fieldset">
                                    <FormGroup>
                                        {this.dataDoc.simulation_Type == 'One Weight' && (
                                            <FormControlLabel
                                                control={<Checkbox checked={BoolCast(this.dataDoc.elasticCollisions)} onChange={() => (this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions)} />}
                                                label="Make collisions elastic"
                                                labelPlacement="start"
                                            />
                                        )}
                                        <FormControlLabel control={<Checkbox checked={BoolCast(this.dataDoc.show_Forces)} onChange={() => (this.dataDoc.show_Forces = !this.dataDoc.show_Forces)} />} label="Show force vectors" labelPlacement="start" />
                                        {(this.dataDoc.simulation_Type == 'Inclined Plane' || this.dataDoc.simulation_Type == 'Pendulum') && (
                                            <FormControlLabel
                                                control={<Checkbox checked={BoolCast(this.dataDoc.show_Forces)} onChange={() => (this.dataDoc.show_ComponentForces = !this.dataDoc.show_ComponentForces)} />}
                                                label="Show component force vectors"
                                                labelPlacement="start"
                                            />
                                        )}
                                        <FormControlLabel
                                            control={<Checkbox checked={BoolCast(this.dataDoc.show_Acceleration)} onChange={() => (this.dataDoc.show_Acceleration = !this.dataDoc.show_Acceleration)} />}
                                            label="Show acceleration vector"
                                            labelPlacement="start"
                                        />
                                        <FormControlLabel
                                            control={<Checkbox checked={BoolCast(this.dataDoc.show_Velocity)} onChange={() => (this.dataDoc.show_Velocity = !this.dataDoc.show_Velocity)} />}
                                            label="Show velocity vector"
                                            labelPlacement="start"
                                        />
                                        <InputField label={<Box>Speed</Box>} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_Speed" step={1} unit={'x'} upperBound={10} value={this.dataDoc.simulation_Speed ?? 2} labelWidth={'5em'} />
                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Circular Motion' && (
                                            <InputField
                                                label={<Box>Gravity</Box>}
                                                lowerBound={-30}
                                                dataDoc={this.dataDoc}
                                                prop="gravity"
                                                step={0.01}
                                                unit={'m/s2'}
                                                upperBound={0}
                                                value={NumCast(this.dataDoc.gravity, -9.81)}
                                                effect={(val: number) => {
                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                }}
                                                labelWidth={'5em'}
                                            />
                                        )}
                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Pulley' && (
                                            <InputField
                                                label={<Box>Mass</Box>}
                                                lowerBound={1}
                                                dataDoc={this.dataDoc}
                                                prop="mass"
                                                step={0.1}
                                                unit={'kg'}
                                                upperBound={5}
                                                value={NumCast(this.dataDoc.mass) ?? 1}
                                                effect={(val: number) => {
                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                }}
                                                labelWidth={'5em'}
                                            />
                                        )}
                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Pulley' && (
                                            <InputField
                                                label={<Box>Red mass</Box>}
                                                lowerBound={1}
                                                dataDoc={this.dataDoc}
                                                prop="mass"
                                                step={0.1}
                                                unit={'kg'}
                                                upperBound={5}
                                                value={NumCast(this.dataDoc.mass) ?? 1}
                                                effect={(val: number) => {
                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                }}
                                                labelWidth={'5em'}
                                            />
                                        )}
                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Pulley' && (
                                            <InputField
                                                label={<Box>Blue mass</Box>}
                                                lowerBound={1}
                                                dataDoc={this.dataDoc}
                                                prop="mass2"
                                                step={0.1}
                                                unit={'kg'}
                                                upperBound={5}
                                                value={NumCast(this.dataDoc.mass2) ?? 1}
                                                effect={(val: number) => {
                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                }}
                                                labelWidth={'5em'}
                                            />
                                        )}
                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Circular Motion' && (
                                            <InputField
                                                label={<Box>Rod length</Box>}
                                                lowerBound={100}
                                                dataDoc={this.dataDoc}
                                                prop="circularMotionRadius"
                                                step={5}
                                                unit={'m'}
                                                upperBound={250}
                                                value={NumCast(this.dataDoc.circularMotionRadius) ?? 100}
                                                effect={(val: number) => {
                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                }}
                                                labelWidth={'5em'}
                                            />
                                        )}
                                    </FormGroup>
                                </FormControl>
                                {this.dataDoc.simulation_Type == 'Spring' && this.dataDoc.simulation_Paused && (
                                    <div>
                                        <InputField
                                            label={<Typography color="inherit">Spring stiffness</Typography>}
                                            lowerBound={0.1}
                                            dataDoc={this.dataDoc}
                                            prop="springConstant"
                                            step={1}
                                            unit={'N/m'}
                                            upperBound={500}
                                            value={NumCast(this.dataDoc.springConstant) ?? 0.5}
                                            effect={(val: number) => {
                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            }}
                                            radianEquivalent={false}
                                            mode={'Freeform'}
                                            labelWidth={'7em'}
                                        />
                                        <InputField
                                            label={<Typography color="inherit">Rest length</Typography>}
                                            lowerBound={10}
                                            dataDoc={this.dataDoc}
                                            prop="springRestLength"
                                            step={100}
                                            unit={''}
                                            upperBound={500}
                                            value={NumCast(this.dataDoc.springRestLength) ?? 200}
                                            effect={(val: number) => {
                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            }}
                                            radianEquivalent={false}
                                            mode={'Freeform'}
                                            labelWidth={'7em'}
                                        />
                                        <InputField
                                            label={<Typography color="inherit">Starting displacement</Typography>}
                                            lowerBound={-(NumCast(this.dataDoc.springRestLength) - 10)}
                                            dataDoc={this.dataDoc}
                                            prop=""
                                            step={10}
                                            unit={''}
                                            upperBound={NumCast(this.dataDoc.springRestLength)}
                                            value={NumCast(this.dataDoc.springStartLength) - NumCast(this.dataDoc.springRestLength)}
                                            effect={(val: number) => {
                                                this.dataDoc.start_PosY = NumCast(this.dataDoc.springRestLength) + val;
                                                this.dataDoc.springStartLength = NumCast(this.dataDoc.springRestLength) + val;
                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            }}
                                            radianEquivalent={false}
                                            mode={'Freeform'}
                                            labelWidth={'7em'}
                                        />
                                    </div>
                                )}
                                {this.dataDoc.simulation_Type == 'Inclined Plane' && this.dataDoc.simulation_Paused && (
                                    <div>
                                        <InputField
                                            label={<Box>&theta;</Box>}
                                            lowerBound={0}
                                            dataDoc={this.dataDoc}
                                            prop="wedgeAngle"
                                            step={1}
                                            unit={'°'}
                                            upperBound={49}
                                            value={NumCast(this.dataDoc.wedgeAngle, 26)}
                                            effect={(val: number) => {
                                                this.changeWedgeBasedOnNewAngle(val);
                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            }}
                                            radianEquivalent={true}
                                            mode={'Freeform'}
                                            labelWidth={'2em'}
                                        />
                                        <InputField
                                            label={
                                                <Box>
                                                    &mu;<sub>s</sub>
                                                </Box>
                                            }
                                            lowerBound={0}
                                            dataDoc={this.dataDoc}
                                            prop="coefficientOfStaticFriction"
                                            step={0.1}
                                            unit={''}
                                            upperBound={1}
                                            value={NumCast(this.dataDoc.coefficientOfStaticFriction) ?? 0}
                                            effect={(val: number) => {
                                                this.updateForcesWithFriction(val);
                                                if (val < NumCast(this.dataDoc.coefficientOfKineticFriction)) {
                                                    this.dataDoc.soefficientOfKineticFriction = val;
                                                }
                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            }}
                                            mode={'Freeform'}
                                            labelWidth={'2em'}
                                        />
                                        <InputField
                                            label={
                                                <Box>
                                                    &mu;<sub>k</sub>
                                                </Box>
                                            }
                                            lowerBound={0}
                                            dataDoc={this.dataDoc}
                                            prop="coefficientOfKineticFriction"
                                            step={0.1}
                                            unit={''}
                                            upperBound={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                            value={NumCast(this.dataDoc.coefficientOfKineticFriction) ?? 0}
                                            effect={(val: number) => {
                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                            }}
                                            mode={'Freeform'}
                                            labelWidth={'2em'}
                                        />
                                    </div>
                                )}
                                {this.dataDoc.simulation_Type == 'Inclined Plane' && !this.dataDoc.simulation_Paused && (
                                    <Typography>
                                        &theta;: {Math.round(NumCast(this.dataDoc.wedgeAngle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedgeAngle) * Math.PI) / 180) * 100) / 100} rad
                                        <br />
                                        &mu; <sub>s</sub>: {this.dataDoc.coefficientOfStaticFriction}
                                        <br />
                                        &mu; <sub>k</sub>: {this.dataDoc.coefficientOfKineticFriction}
                                    </Typography>
                                )}
                                {this.dataDoc.simulation_Type == 'Pendulum' && !this.dataDoc.simulation_Paused && (
                                    <Typography>
                                        &theta;: {Math.round(NumCast(this.dataDoc.pendulum_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.pendulum_angle) * Math.PI) / 180) * 100) / 100} rad
                                    </Typography>
                                )}
                                {this.dataDoc.simulation_Type == 'Pendulum' && this.dataDoc.simulation_Paused && (
                                    <div>
                                        <InputField
                                            label={<Box>Angle</Box>}
                                            lowerBound={0}
                                            dataDoc={this.dataDoc}
                                            prop="pendulum_angle"
                                            step={1}
                                            unit={'°'}
                                            upperBound={59}
                                            value={NumCast(this.dataDoc.pendulum_angle, 30)}
                                            effect={value => {
                                                this.dataDoc.start_PendulumAngle = value;
                                                if (this.dataDoc.simulation_Type == 'Pendulum') {
                                                    const mag = NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((value * Math.PI) / 180);

                                                    const forceOfTension: IForce = {
                                                        description: 'Tension',
                                                        magnitude: mag,
                                                        directionInDegrees: 90 - value,
                                                        component: false,
                                                    };

                                                    const tensionComponent: IForce = {
                                                        description: 'Tension',
                                                        magnitude: mag,
                                                        directionInDegrees: 90 - value,
                                                        component: true,
                                                    };
                                                    const gravityParallel: IForce = {
                                                        description: 'Gravity Parallel Component',
                                                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((value * Math.PI) / 180),
                                                        directionInDegrees: 270 - value,
                                                        component: true,
                                                    };
                                                    const gravityPerpendicular: IForce = {
                                                        description: 'Gravity Perpendicular Component',
                                                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.sin((value * Math.PI) / 180),
                                                        directionInDegrees: -value,
                                                        component: true,
                                                    };

                                                    const length = NumCast(this.dataDoc.pendulum_length);
                                                    const x = length * Math.cos(((90 - value) * Math.PI) / 180);
                                                    const y = length * Math.sin(((90 - value) * Math.PI) / 180);
                                                    const xPos = this.xMax / 2 - x - NumCast(this.dataDoc.radius);
                                                    const yPos = y - NumCast(this.dataDoc.radius) - 5;
                                                    this.dataDoc.start_PosX = xPos;
                                                    this.dataDoc.start_PosY = yPos;

                                                    this.dataDoc.start_Forces = [
                                                        {
                                                            description: 'Gravity',
                                                            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                                                            directionInDegrees: 270,
                                                            component: false,
                                                        },
                                                        forceOfTension,
                                                    ];
                                                    this.dataDoc.updatedForces = [
                                                        {
                                                            description: 'Gravity',
                                                            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                                                            directionInDegrees: 270,
                                                            component: false,
                                                        },
                                                        forceOfTension,
                                                    ];
                                                    this.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
                                                    this.dataDoc.pendulum_angle_adjust = value;
                                                    (this.dataDoc.pendulum_length_adjust = this.dataDoc.pendulum_length), (this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset);
                                                }
                                            }}
                                            radianEquivalent={true}
                                            mode={'Freeform'}
                                            labelWidth={'5em'}
                                        />
                                        <InputField
                                            label={<Box>Rod length</Box>}
                                            lowerBound={0}
                                            dataDoc={this.dataDoc}
                                            prop="pendulum_length"
                                            step={1}
                                            unit={'m'}
                                            upperBound={400}
                                            value={Math.round(NumCast(this.dataDoc.pendulum_length))}
                                            effect={value => {
                                                if (this.dataDoc.simulation_Type == 'Pendulum') {
                                                    this.dataDoc.pendulum_angle_adjust = NumCast(this.dataDoc.pendulum_angle);
                                                    this.dataDoc.pendulum_length_adjust = value;
                                                    this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                                }
                                            }}
                                            radianEquivalent={false}
                                            mode={'Freeform'}
                                            labelWidth={'5em'}
                                        />
                                    </div>
                                )}
                            </div>
                        )}
                        <div className="mechanicsSimulationEquation">
                            {this.dataDoc.mode == 'Freeform' && (
                                <table>
                                    <tbody>
                                        <tr>
                                            <td>{this.dataDoc.simulation_Type == 'Pulley' ? 'Red Weight' : ''}</td>
                                            <td>X</td>
                                            <td>Y</td>
                                        </tr>
                                        <tr>
                                            <td
                                                style={{ cursor: 'help' }}
                                                // onClick={() => {
                                                //   window.open(
                                                //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
                                                //   );
                                                // }}
                                            >
                                                <Box>Position</Box>
                                            </td>
                                            {(!this.dataDoc.simulation_Paused || this.dataDoc.simulation_Type == 'Inclined Plane' || this.dataDoc.simulation_Type == 'Circular Motion' || this.dataDoc.simulation_Type == 'Pulley') && (
                                                <td style={{ cursor: 'default' }}>{this.dataDoc.position_XDisplay} m</td>
                                            )}{' '}
                                            {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Inclined Plane' && this.dataDoc.simulation_Type != 'Circular Motion' && this.dataDoc.simulation_Type != 'Pulley' && (
                                                <td
                                                    style={{
                                                        cursor: 'default',
                                                    }}>
                                                    <InputField
                                                        lowerBound={this.dataDoc.simulation_Type == 'Projectile' ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
                                                        dataDoc={this.dataDoc}
                                                        prop="position_XDisplay"
                                                        step={1}
                                                        unit={'m'}
                                                        upperBound={this.dataDoc.simulation_Type == 'Projectile' ? this.xMax - 110 : (3 * (this.xMax + this.xMin)) / 4 - this.radius / 2 - 15}
                                                        value={NumCast(this.dataDoc.position_XDisplay)}
                                                        effect={value => {
                                                            this.dataDoc.display_xChange = value;
                                                            this.dataDoc.display_yChange = this.dataDoc.position_YDisplay;
                                                            if (this.dataDoc.simulation_Type == 'Suspension') {
                                                                let x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200;
                                                                let x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius;
                                                                let deltaX1 = value + this.radius - x1rod;
                                                                let deltaX2 = x2rod - (value + this.radius);
                                                                let deltaY = this.getYPosFromDisplay(NumCast(this.dataDoc.position_YDisplay)) + this.radius;
                                                                let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
                                                                let dir2T = Math.atan(deltaY / deltaX2);
                                                                let tensionMag2 = (NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity))) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
                                                                let tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T);
                                                                dir1T = (dir1T * 180) / Math.PI;
                                                                dir2T = (dir2T * 180) / Math.PI;
                                                                const tensionForce1: IForce = {
                                                                    description: 'Tension',
                                                                    magnitude: tensionMag1,
                                                                    directionInDegrees: dir1T,
                                                                    component: false,
                                                                };
                                                                const tensionForce2: IForce = {
                                                                    description: 'Tension',
                                                                    magnitude: tensionMag2,
                                                                    directionInDegrees: dir2T,
                                                                    component: false,
                                                                };
                                                                const grav: IForce = {
                                                                    description: 'Gravity',
                                                                    magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                                                                    directionInDegrees: 270,
                                                                    component: false,
                                                                };
                                                                this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
                                                            }
                                                        }}
                                                        small={true}
                                                        mode={'Freeform'}
                                                    />
                                                </td>
                                            )}{' '}
                                            {(!this.dataDoc.simulation_Paused || this.dataDoc.simulation_Type == 'Inclined Plane' || this.dataDoc.simulation_Type == 'Circular Motion' || this.dataDoc.simulation_Type == 'Pulley') && (
                                                <td style={{ cursor: 'default' }}>{`${NumCast(this.dataDoc.position_YDisplay)} m`}</td>
                                            )}{' '}
                                            {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Inclined Plane' && this.dataDoc.simulation_Type != 'Circular Motion' && this.dataDoc.simulation_Type != 'Pulley' && (
                                                <td
                                                    style={{
                                                        cursor: 'default',
                                                    }}>
                                                    <InputField
                                                        lowerBound={1}
                                                        dataDoc={this.dataDoc}
                                                        prop="position_YDisplay"
                                                        step={1}
                                                        unit={'m'}
                                                        upperBound={this.yMax - 110}
                                                        value={NumCast(this.dataDoc.position_YDisplay)}
                                                        effect={value => {
                                                            this.dataDoc.display_xChange = NumCast(this.dataDoc.position_XDisplay);
                                                            this.dataDoc.display_yChange = value;
                                                            if (this.dataDoc.simulation_Type == 'Suspension') {
                                                                let x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200;
                                                                let x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius;
                                                                let deltaX1 = NumCast(this.dataDoc.position_XDisplay) + this.radius - x1rod;
                                                                let deltaX2 = x2rod - (NumCast(this.dataDoc.position_XDisplay) + this.radius);
                                                                let deltaY = this.getYPosFromDisplay(value) + this.radius;
                                                                let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
                                                                let dir2T = Math.atan(deltaY / deltaX2);
                                                                let tensionMag2 = (NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity))) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
                                                                let tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T);
                                                                dir1T = (dir1T * 180) / Math.PI;
                                                                dir2T = (dir2T * 180) / Math.PI;
                                                                const tensionForce1: IForce = {
                                                                    description: 'Tension',
                                                                    magnitude: tensionMag1,
                                                                    directionInDegrees: dir1T,
                                                                    component: false,
                                                                };
                                                                const tensionForce2: IForce = {
                                                                    description: 'Tension',
                                                                    magnitude: tensionMag2,
                                                                    directionInDegrees: dir2T,
                                                                    component: false,
                                                                };
                                                                const grav: IForce = {
                                                                    description: 'Gravity',
                                                                    magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                                                                    directionInDegrees: 270,
                                                                    component: false,
                                                                };
                                                                this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
                                                            }
                                                        }}
                                                        small={true}
                                                        mode={'Freeform'}
                                                    />
                                                </td>
                                            )}{' '}
                                        </tr>
                                        <tr>
                                            <td
                                                style={{ cursor: 'help' }}
                                                // onClick={() => {
                                                //   window.open(
                                                //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
                                                //   );
                                                // }}
                                            >
                                                <Box>Velocity</Box>
                                            </td>
                                            {(!this.dataDoc.simulation_Paused || (this.dataDoc.simulation_Type != 'One Weight' && this.dataDoc.simulation_Type != 'Circular Motion')) && (
                                                <td style={{ cursor: 'default' }}>{`${NumCast(this.dataDoc.velocity_XDisplay)} m/s`}</td>
                                            )}{' '}
                                            {this.dataDoc.simulation_Paused && (this.dataDoc.simulation_Type == 'One Weight' || this.dataDoc.simulation_Type == 'Circular Motion') && (
                                                <td
                                                    style={{
                                                        cursor: 'default',
                                                    }}>
                                                    <InputField
                                                        lowerBound={-50}
                                                        dataDoc={this.dataDoc}
                                                        prop="velocity_XDisplay"
                                                        step={1}
                                                        unit={'m/s'}
                                                        upperBound={50}
                                                        value={this.dataDoc.velocity_XDisplay}
                                                        effect={value => {
                                                            this.dataDoc.start_VelX = value;
                                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                                        }}
                                                        small={true}
                                                        mode={'Freeform'}
                                                    />
                                                </td>
                                            )}{' '}
                                            {(!this.dataDoc.simulation_Paused || this.dataDoc.simulation_Type != 'One Weight') && <td style={{ cursor: 'default' }}>{this.dataDoc.velocity_YDisplay} m/s</td>}{' '}
                                            {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'One Weight' && (
                                                <td
                                                    style={{
                                                        cursor: 'default',
                                                    }}>
                                                    <InputField
                                                        lowerBound={-50}
                                                        dataDoc={this.dataDoc}
                                                        prop="velocity_YDisplay"
                                                        step={1}
                                                        unit={'m/s'}
                                                        upperBound={50}
                                                        value={this.dataDoc.velocity_YDisplay}
                                                        effect={value => {
                                                            this.dataDoc.start_VelY = -value;
                                                            this.dataDoc.display_xChange = this.dataDoc.position_XDisplay;
                                                            this.dataDoc.display_yChange = this.dataDoc.position_YDisplay;
                                                        }}
                                                        small={true}
                                                        mode={'Freeform'}
                                                    />
                                                </td>
                                            )}{' '}
                                        </tr>
                                        <tr>
                                            <td
                                                style={{ cursor: 'help' }}
                                                // onClick={() => {
                                                //   window.open(
                                                //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
                                                //   );
                                                // }}
                                            >
                                                <Box>Acceleration</Box>
                                            </td>
                                            <td style={{ cursor: 'default' }}>
                                                {this.dataDoc.acceleration_XDisplay} m/s<sup>2</sup>
                                            </td>
                                            <td style={{ cursor: 'default' }}>
                                                {this.dataDoc.acceleration_YDisplay} m/s<sup>2</sup>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                                                <Box>Momentum</Box>
                                            </td>
                                            <td>{Math.round(this.dataDoc.velocity_XDisplay * this.dataDoc.mass * 10) / 10} kg*m/s</td>
                                            <td>{Math.round(this.dataDoc.velocity_YDisplay * this.dataDoc.mass * 10) / 10} kg*m/s</td>
                                        </tr>
                                    </tbody>
                                </table>
                            )}
                            {this.dataDoc.mode == 'Freeform' && this.dataDoc.simulation_Type == 'Pulley' && (
                                <table>
                                    <tbody>
                                        <tr>
                                            <td>Blue Weight</td>
                                            <td>X</td>
                                            <td>Y</td>
                                        </tr>
                                        <tr>
                                            <td>
                                                <Box>Position</Box>
                                            </td>
                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.position_XDisplay2} m`}</td>
                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.position_YDisplay2} m`}</td>
                                        </tr>
                                        <tr>
                                            <td>
                                                <Box>Velocity</Box>
                                            </td>
                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.position_XDisplay2} m/s`}</td>
                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.position_YDisplay2} m/s`}</td>
                                        </tr>
                                        <tr>
                                            <td>
                                                <Box>Acceleration</Box>
                                            </td>
                                            <td style={{ cursor: 'default' }}>
                                                {this.dataDoc.acceleration_XDisplay2} m/s<sup>2</sup>
                                            </td>
                                            <td style={{ cursor: 'default' }}>
                                                {this.dataDoc.acceleration_YDisplay2} m/s<sup>2</sup>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                                                <Box>Momentum</Box>
                                            </td>
                                            <td>{Math.round(NumCast(this.dataDoc.velocity_XDisplay2) * NumCast(this.dataDoc.mass) * 10) / 10} kg*m/s</td>
                                            <td>{Math.round(NumCast(this.dataDoc.velocity_YDisplay2) * NumCast(this.dataDoc.mass) * 10) / 10} kg*m/s</td>
                                        </tr>
                                    </tbody>
                                </table>
                            )}
                        </div>
                        {this.dataDoc.simulation_Type != 'Pendulum' && this.dataDoc.simulation_Type != 'Spring' && (
                            <div>
                                <p>Kinematic Equations</p>
                                <ul>
                                    <li>
                                        Position: x<sub>1</sub>=x<sub>0</sub>+v<sub>0</sub>t+
                                        <sup>1</sup>&frasl;
                                        <sub>2</sub>at
                                        <sup>2</sup>
                                    </li>
                                    <li>
                                        Velocity: v<sub>1</sub>=v<sub>0</sub>+at
                                    </li>
                                    <li>Acceleration: a = F/m</li>
                                </ul>
                            </div>
                        )}
                        {this.dataDoc.simulation_Type == 'Spring' && (
                            <div>
                                <p>Harmonic Motion Equations: Spring</p>
                                <ul>
                                    <li>
                                        Spring force: F<sub>s</sub>=kd
                                    </li>
                                    <li>
                                        Spring period: T<sub>s</sub>=2&pi;&#8730;<sup>m</sup>&frasl;
                                        <sub>k</sub>
                                    </li>
                                    <li>Equilibrium displacement for vertical spring: d = mg/k</li>
                                    <li>
                                        Elastic potential energy: U<sub>s</sub>=<sup>1</sup>&frasl;
                                        <sub>2</sub>kd<sup>2</sup>
                                    </li>
                                    <ul>
                                        <li>Maximum when system is at maximum displacement, 0 when system is at 0 displacement</li>
                                    </ul>
                                    <li>
                                        Translational kinetic energy: K=<sup>1</sup>&frasl;
                                        <sub>2</sub>mv<sup>2</sup>
                                    </li>
                                    <ul>
                                        <li>Maximum when system is at maximum/minimum velocity (at 0 displacement), 0 when velocity is 0 (at maximum displacement)</li>
                                    </ul>
                                </ul>
                            </div>
                        )}
                        {this.dataDoc.simulation_Type == 'Pendulum' && (
                            <div>
                                <p>Harmonic Motion Equations: Pendulum</p>
                                <ul>
                                    <li>
                                        Pendulum period: T<sub>p</sub>=2&pi;&#8730;<sup>l</sup>&frasl;
                                        <sub>g</sub>
                                    </li>
                                </ul>
                            </div>
                        )}
                    </div>
                </div>
                <div
                    style={{
                        position: 'fixed',
                        top: this.yMax - 120 + 20 + 'px',
                        left: this.xMin + 90 - 80 + 'px',
                        zIndex: -10000,
                    }}>
                    <svg width={100 + 'px'} height={100 + 'px'}>
                        <defs>
                            <marker id="miniArrow" markerWidth="20" markerHeight="20" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                <path d="M0,0 L0,6 L9,3 z" fill={'#000000'} />
                            </marker>
                        </defs>
                        <line x1={20} y1={70} x2={70} y2={70} stroke={'#000000'} strokeWidth="2" markerEnd="url(#miniArrow)" />
                        <line x1={20} y1={70} x2={20} y2={20} stroke={'#000000'} strokeWidth="2" markerEnd="url(#miniArrow)" />
                    </svg>
                    <p
                        style={{
                            position: 'fixed',
                            top: this.yMax - 120 + 40 + 'px',
                            left: this.xMin + 90 - 80 + 'px',
                        }}>
                        {this.dataDoc.simulation_Type == 'Circular Motion' ? 'Z' : 'Y'}
                    </p>
                    <p
                        style={{
                            position: 'fixed',
                            top: this.yMax - 120 + 80 + 'px',
                            left: this.xMin + 90 - 40 + 'px',
                        }}>
                        X
                    </p>
                </div>
            </div>
        );
    }
}
